Fossil SCM

The filename/version block on the first fileedit tab is now generated completely dynamically, rather than being filled out with '???' with broken links before a file is loaded.

stephan 2020-05-14 03:39 fileedit-ajaxify
Commit 371b162ff38c0b2154efec53a72421aa675436029418c1c3a6a97f9435559050
--- src/default_css.txt
+++ src/default_css.txt
@@ -944,17 +944,18 @@
944944
border-left-style: outset;
945945
border-right-style: outset;
946946
}
947947
//////////////////////////////////
948948
// Styles for /fileedit:
949
-textarea.fileedit {
949
+body.fileedit textarea {
950950
font-family: monospace;
951951
width: 100%;
952952
flex: 10 1 auto;
953953
}
954954
body.fileedit fieldset {
955955
margin: 0.5em 0 0.5em 0;
956
+ padding: 0.25em 0;
956957
border-radius: 0.5em;
957958
border-color: inherit;
958959
border-width: 1px;
959960
font-size: 85%;
960961
}
961962
--- src/default_css.txt
+++ src/default_css.txt
@@ -944,17 +944,18 @@
944 border-left-style: outset;
945 border-right-style: outset;
946 }
947 //////////////////////////////////
948 // Styles for /fileedit:
949 textarea.fileedit {
950 font-family: monospace;
951 width: 100%;
952 flex: 10 1 auto;
953 }
954 body.fileedit fieldset {
955 margin: 0.5em 0 0.5em 0;
 
956 border-radius: 0.5em;
957 border-color: inherit;
958 border-width: 1px;
959 font-size: 85%;
960 }
961
--- src/default_css.txt
+++ src/default_css.txt
@@ -944,17 +944,18 @@
944 border-left-style: outset;
945 border-right-style: outset;
946 }
947 //////////////////////////////////
948 // Styles for /fileedit:
949 body.fileedit textarea {
950 font-family: monospace;
951 width: 100%;
952 flex: 10 1 auto;
953 }
954 body.fileedit fieldset {
955 margin: 0.5em 0 0.5em 0;
956 padding: 0.25em 0;
957 border-radius: 0.5em;
958 border-color: inherit;
959 border-width: 1px;
960 font-size: 85%;
961 }
962
+4 -13
--- src/fileedit.c
+++ src/fileedit.c
@@ -1755,23 +1755,14 @@
17551755
{
17561756
CX("<div id='fileedit-tab-version' "
17571757
"data-tab-parent='fileedit-tabs' "
17581758
"data-tab-label='File Info &amp; Selection'"
17591759
">");
1760
- CX("File: "
1761
- "<code id='finfo-file-name'>" "???" "</code><br>");
1762
- CX("Checkin Version: "
1763
- "[<a id='timeline-link' href='#'>/timeline</a>] "
1764
- "[<a id='r-link' href='#'>/info</a>] "
1765
- /* %R/info/%!S */
1766
- "<code id='r-label'>" "???" "</code><br>"
1767
- );
1768
- CX("Permalink: <code>"
1769
- "<a id='permalink' href='#'>" "???" "</a></code><br>"
1770
- "(Clicking the permalink will reload the page and discard "
1771
- "all edits!)");
1772
-
1760
+ CX("<fieldset id='file-version-details'>"
1761
+ "<legend>File/Version</legend>"
1762
+ "<div>No file loaded.</div>"
1763
+ "</fieldset>");
17731764
CX("<h1>Select a file to edit:</h1>");
17741765
CX("<div id='fileedit-file-selector'></div>");
17751766
CX("</div>"/*#fileedit-tab-version*/);
17761767
}
17771768
17781769
--- src/fileedit.c
+++ src/fileedit.c
@@ -1755,23 +1755,14 @@
1755 {
1756 CX("<div id='fileedit-tab-version' "
1757 "data-tab-parent='fileedit-tabs' "
1758 "data-tab-label='File Info &amp; Selection'"
1759 ">");
1760 CX("File: "
1761 "<code id='finfo-file-name'>" "???" "</code><br>");
1762 CX("Checkin Version: "
1763 "[<a id='timeline-link' href='#'>/timeline</a>] "
1764 "[<a id='r-link' href='#'>/info</a>] "
1765 /* %R/info/%!S */
1766 "<code id='r-label'>" "???" "</code><br>"
1767 );
1768 CX("Permalink: <code>"
1769 "<a id='permalink' href='#'>" "???" "</a></code><br>"
1770 "(Clicking the permalink will reload the page and discard "
1771 "all edits!)");
1772
1773 CX("<h1>Select a file to edit:</h1>");
1774 CX("<div id='fileedit-file-selector'></div>");
1775 CX("</div>"/*#fileedit-tab-version*/);
1776 }
1777
1778
--- src/fileedit.c
+++ src/fileedit.c
@@ -1755,23 +1755,14 @@
1755 {
1756 CX("<div id='fileedit-tab-version' "
1757 "data-tab-parent='fileedit-tabs' "
1758 "data-tab-label='File Info &amp; Selection'"
1759 ">");
1760 CX("<fieldset id='file-version-details'>"
1761 "<legend>File/Version</legend>"
1762 "<div>No file loaded.</div>"
1763 "</fieldset>");
 
 
 
 
 
 
 
 
 
1764 CX("<h1>Select a file to edit:</h1>");
1765 CX("<div id='fileedit-file-selector'></div>");
1766 CX("</div>"/*#fileedit-tab-version*/);
1767 }
1768
1769
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -208,10 +208,11 @@
208208
selectHtmlEmsWrap: E('#select-preview-html-ems'),
209209
selectEolWrap: E('#select-preview-html-ems'),
210210
cbLineNumbersWrap: E('#cb-line-numbers'),
211211
cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
212212
cbIsExe: E('input[type=checkbox][name=exec_bit]'),
213
+ fsFileVersionDetails: E('#file-version-details'),
213214
tabs:{
214215
content: E('#fileedit-tab-content'),
215216
preview: E('#fileedit-tab-preview'),
216217
diff: E('#fileedit-tab-diff'),
217218
commit: E('#fileedit-tab-commit')
@@ -420,59 +421,75 @@
420421
this.e.taComment = s;
421422
D.addClass(h, 'hidden');
422423
D.removeClass(s, 'hidden');
423424
console.debug(s,h);
424425
};
426
+
427
+ /**
428
+ Returns true if fossil.page.finfo is set, indicating that a file
429
+ has been loaded, else it reports an error and returns false.
430
+ */
431
+ const affirmHasFile = function(){
432
+ if(!P.finfo) F.error("No file is loaded.");
433
+ return !!P.finfo;
434
+ };
425435
426436
/**
427437
updateVersion() updates the filename and version in various UI
428438
elements...
429439
430440
Returns this object.
431441
*/
432442
P.updateVersion = function(file,rev){
433
- this.finfo = {filename:file,checkin:rev};
434
- const E = (s)=>document.querySelector(s),
435
- euc = encodeURIComponent,
443
+ if(1===arguments.length){/*assume object*/
444
+ this.finfo = arguments[0];
445
+ file = this.finfo.filename;
446
+ rev = this.finfo.checkin;
447
+ }else if(0===arguments.length){
448
+ if(!affirmHasFile()) return this;
449
+ }else{
450
+ this.finfo = {filename:file,checkin:rev};
451
+ }
452
+ const eTgt = this.e.fsFileVersionDetails.querySelector('div'),
436453
rHuman = F.hashDigits(rev),
437454
rUrl = F.hashDigits(rev,true);
438
- D.append(
439
- D.clearElement(E('#r-label')),
440
- rHuman
441
- );
442
- var e;
443
- e = E('#timeline-link');
444
- D.attr(e, 'href',F.repoUrl('timeline',{c:rUrl}));
445
- e = E('#finfo-file-name');
446
- D.append(
447
- D.clearElement(e),
448
- D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)
449
- );
450
- e = E('#r-link');
451
- D.attr(e, 'href', F.repoUrl('info/'+rUrl));
452
- e = E('#r-label');
453
- D.append(D.clearElement(e),rHuman);
455
+ D.clearElement(eTgt);
456
+ D.append(
457
+ eTgt, "File: ",
458
+ D.append(D.code(),
459
+ D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)),
460
+ D.br()
461
+ );
462
+ D.append(
463
+ eTgt, "Checkin Version: ",
464
+ D.append(D.code(), D.a(F.repoUrl('info/'+rUrl), rHuman)),
465
+ " [",D.a(F.repoUrl('timeline',{m:rUrl}), "timeline"),"]",
466
+ D.br()
467
+ );
468
+ D.append(
469
+ eTgt, "Mimetype: ",
470
+ D.append(D.code(), this.finfo.mimetype||'???'),
471
+ D.br()
472
+ );
454473
const purlArgs = F.encodeUrlArgs({
455474
filename: this.finfo.filename,
456475
checkin: rUrl
457476
},false,true);
458477
const purl = F.repoUrl('fileedit',purlArgs);
459
- e = E('#permalink');
460
- D.attr(D.append(D.clearElement(e),'?'+purlArgs),'href', purl);
478
+ D.append(
479
+ eTgt,
480
+ "Permalink: ",
481
+ D.append(D.code(),D.a(purl,true))
482
+ );
461483
return this;
462484
};
463485
464
- const affirmHasFile = function(){
465
- if(!P.finfo) F.error("No file is loaded.");
466
- return !!P.finfo;
467
- };
468
-
469486
/**
470487
loadFile() loads (file,checkinVersion) and updates the relevant
471488
UI elements to reflect the loaded state. If passed no arguments
472
- then it re-uses the values from the currently-loaded file
473
- (becoming a no-op if no file is loaded).
489
+ then it re-uses the values from the currently-loaded file, reloading
490
+ it (emitting an error message if no file is loaded).
474491
475492
Returns this object, noting that the load is async. After loading
476493
it triggers a 'fileedit-file-loaded' event, passing it
477494
this.finfo.
478495
*/
@@ -492,13 +509,16 @@
492509
checkin:rev
493510
},
494511
responseHeaders: ['x-fileedit-file-perm', 'content-type'],
495512
onload:(r,headers)=>{
496513
F.message('Loaded content.');
497
- self.updateVersion(file,rev);
498
- self.finfo.isExe = ('x'===headers['x-fileedit-file-perm']);
499
- self.finfo.mimetype = headers['content-type'].split(';').shift();
514
+ self.updateVersion({
515
+ filename: file,
516
+ checkin: rev,
517
+ isExe: ('x'===headers['x-fileedit-file-perm']),
518
+ mimetype: headers['content-type'].split(';').shift()
519
+ });
500520
self.tabs.switchToTab(self.e.tabs.content);
501521
self.e.cbIsExe.checked = self.finfo.isExe;
502522
self.value(r);
503523
self.dispatchEvent('fileedit-file-loaded', self.finfo);
504524
}
@@ -635,14 +655,16 @@
635655
];
636656
if(!c.dryRun){
637657
msg.push('Re-activating dry-run mode.');
638658
self.e.taComment.value = '';
639659
cbDryRun.checked = true;
640
- self.updateVersion(filename, c.uuid);
660
+ self.finfo.filename = filename;
661
+ self.finfo.checkin = c.uuid;
662
+ self.updateVersion();
641663
self.fileSelector.loadLeaves();
642664
}
643
- F.message.apply(fossil, msg);
665
+ F.message.apply(F, msg);
644666
self.tabs.switchToTab(self.e.tabs.commit);
645667
};
646668
}
647669
if(!content){
648670
f.updateView('');
649671
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -208,10 +208,11 @@
208 selectHtmlEmsWrap: E('#select-preview-html-ems'),
209 selectEolWrap: E('#select-preview-html-ems'),
210 cbLineNumbersWrap: E('#cb-line-numbers'),
211 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
212 cbIsExe: E('input[type=checkbox][name=exec_bit]'),
 
213 tabs:{
214 content: E('#fileedit-tab-content'),
215 preview: E('#fileedit-tab-preview'),
216 diff: E('#fileedit-tab-diff'),
217 commit: E('#fileedit-tab-commit')
@@ -420,59 +421,75 @@
420 this.e.taComment = s;
421 D.addClass(h, 'hidden');
422 D.removeClass(s, 'hidden');
423 console.debug(s,h);
424 };
 
 
 
 
 
 
 
 
 
425
426 /**
427 updateVersion() updates the filename and version in various UI
428 elements...
429
430 Returns this object.
431 */
432 P.updateVersion = function(file,rev){
433 this.finfo = {filename:file,checkin:rev};
434 const E = (s)=>document.querySelector(s),
435 euc = encodeURIComponent,
 
 
 
 
 
 
 
436 rHuman = F.hashDigits(rev),
437 rUrl = F.hashDigits(rev,true);
438 D.append(
439 D.clearElement(E('#r-label')),
440 rHuman
441 );
442 var e;
443 e = E('#timeline-link');
444 D.attr(e, 'href',F.repoUrl('timeline',{c:rUrl}));
445 e = E('#finfo-file-name');
446 D.append(
447 D.clearElement(e),
448 D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)
449 );
450 e = E('#r-link');
451 D.attr(e, 'href', F.repoUrl('info/'+rUrl));
452 e = E('#r-label');
453 D.append(D.clearElement(e),rHuman);
 
 
454 const purlArgs = F.encodeUrlArgs({
455 filename: this.finfo.filename,
456 checkin: rUrl
457 },false,true);
458 const purl = F.repoUrl('fileedit',purlArgs);
459 e = E('#permalink');
460 D.attr(D.append(D.clearElement(e),'?'+purlArgs),'href', purl);
 
 
 
461 return this;
462 };
463
464 const affirmHasFile = function(){
465 if(!P.finfo) F.error("No file is loaded.");
466 return !!P.finfo;
467 };
468
469 /**
470 loadFile() loads (file,checkinVersion) and updates the relevant
471 UI elements to reflect the loaded state. If passed no arguments
472 then it re-uses the values from the currently-loaded file
473 (becoming a no-op if no file is loaded).
474
475 Returns this object, noting that the load is async. After loading
476 it triggers a 'fileedit-file-loaded' event, passing it
477 this.finfo.
478 */
@@ -492,13 +509,16 @@
492 checkin:rev
493 },
494 responseHeaders: ['x-fileedit-file-perm', 'content-type'],
495 onload:(r,headers)=>{
496 F.message('Loaded content.');
497 self.updateVersion(file,rev);
498 self.finfo.isExe = ('x'===headers['x-fileedit-file-perm']);
499 self.finfo.mimetype = headers['content-type'].split(';').shift();
 
 
 
500 self.tabs.switchToTab(self.e.tabs.content);
501 self.e.cbIsExe.checked = self.finfo.isExe;
502 self.value(r);
503 self.dispatchEvent('fileedit-file-loaded', self.finfo);
504 }
@@ -635,14 +655,16 @@
635 ];
636 if(!c.dryRun){
637 msg.push('Re-activating dry-run mode.');
638 self.e.taComment.value = '';
639 cbDryRun.checked = true;
640 self.updateVersion(filename, c.uuid);
 
 
641 self.fileSelector.loadLeaves();
642 }
643 F.message.apply(fossil, msg);
644 self.tabs.switchToTab(self.e.tabs.commit);
645 };
646 }
647 if(!content){
648 f.updateView('');
649
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -208,10 +208,11 @@
208 selectHtmlEmsWrap: E('#select-preview-html-ems'),
209 selectEolWrap: E('#select-preview-html-ems'),
210 cbLineNumbersWrap: E('#cb-line-numbers'),
211 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
212 cbIsExe: E('input[type=checkbox][name=exec_bit]'),
213 fsFileVersionDetails: E('#file-version-details'),
214 tabs:{
215 content: E('#fileedit-tab-content'),
216 preview: E('#fileedit-tab-preview'),
217 diff: E('#fileedit-tab-diff'),
218 commit: E('#fileedit-tab-commit')
@@ -420,59 +421,75 @@
421 this.e.taComment = s;
422 D.addClass(h, 'hidden');
423 D.removeClass(s, 'hidden');
424 console.debug(s,h);
425 };
426
427 /**
428 Returns true if fossil.page.finfo is set, indicating that a file
429 has been loaded, else it reports an error and returns false.
430 */
431 const affirmHasFile = function(){
432 if(!P.finfo) F.error("No file is loaded.");
433 return !!P.finfo;
434 };
435
436 /**
437 updateVersion() updates the filename and version in various UI
438 elements...
439
440 Returns this object.
441 */
442 P.updateVersion = function(file,rev){
443 if(1===arguments.length){/*assume object*/
444 this.finfo = arguments[0];
445 file = this.finfo.filename;
446 rev = this.finfo.checkin;
447 }else if(0===arguments.length){
448 if(!affirmHasFile()) return this;
449 }else{
450 this.finfo = {filename:file,checkin:rev};
451 }
452 const eTgt = this.e.fsFileVersionDetails.querySelector('div'),
453 rHuman = F.hashDigits(rev),
454 rUrl = F.hashDigits(rev,true);
455 D.clearElement(eTgt);
456 D.append(
457 eTgt, "File: ",
458 D.append(D.code(),
459 D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)),
460 D.br()
461 );
462 D.append(
463 eTgt, "Checkin Version: ",
464 D.append(D.code(), D.a(F.repoUrl('info/'+rUrl), rHuman)),
465 " [",D.a(F.repoUrl('timeline',{m:rUrl}), "timeline"),"]",
466 D.br()
467 );
468 D.append(
469 eTgt, "Mimetype: ",
470 D.append(D.code(), this.finfo.mimetype||'???'),
471 D.br()
472 );
473 const purlArgs = F.encodeUrlArgs({
474 filename: this.finfo.filename,
475 checkin: rUrl
476 },false,true);
477 const purl = F.repoUrl('fileedit',purlArgs);
478 D.append(
479 eTgt,
480 "Permalink: ",
481 D.append(D.code(),D.a(purl,true))
482 );
483 return this;
484 };
485
 
 
 
 
 
486 /**
487 loadFile() loads (file,checkinVersion) and updates the relevant
488 UI elements to reflect the loaded state. If passed no arguments
489 then it re-uses the values from the currently-loaded file, reloading
490 it (emitting an error message if no file is loaded).
491
492 Returns this object, noting that the load is async. After loading
493 it triggers a 'fileedit-file-loaded' event, passing it
494 this.finfo.
495 */
@@ -492,13 +509,16 @@
509 checkin:rev
510 },
511 responseHeaders: ['x-fileedit-file-perm', 'content-type'],
512 onload:(r,headers)=>{
513 F.message('Loaded content.');
514 self.updateVersion({
515 filename: file,
516 checkin: rev,
517 isExe: ('x'===headers['x-fileedit-file-perm']),
518 mimetype: headers['content-type'].split(';').shift()
519 });
520 self.tabs.switchToTab(self.e.tabs.content);
521 self.e.cbIsExe.checked = self.finfo.isExe;
522 self.value(r);
523 self.dispatchEvent('fileedit-file-loaded', self.finfo);
524 }
@@ -635,14 +655,16 @@
655 ];
656 if(!c.dryRun){
657 msg.push('Re-activating dry-run mode.');
658 self.e.taComment.value = '';
659 cbDryRun.checked = true;
660 self.finfo.filename = filename;
661 self.finfo.checkin = c.uuid;
662 self.updateVersion();
663 self.fileSelector.loadLeaves();
664 }
665 F.message.apply(F, msg);
666 self.tabs.switchToTab(self.e.tabs.commit);
667 };
668 }
669 if(!content){
670 f.updateView('');
671

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button