Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | After committing, reload the leaves/files list. Added a reload button to the leaves/files widget. Several style improvements. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | fileedit-ajaxify |
| Files: | files | file ages | folders |
| SHA3-256: |
2318c419c9e2c3c13e17ae6be8ac601b |
| User & Date: | stephan 2020-05-12 08:28:28.796 |
Context
|
2020-05-12
| ||
| 08:54 | Double-clicking the status message bar now clears the message (useful when a long HTML-format error comes in via ajax). Removed the unsightly 'new and experimental' banner. ... (check-in: ff7ad7125f user: stephan tags: fileedit-ajaxify) | |
| 08:28 | After committing, reload the leaves/files list. Added a reload button to the leaves/files widget. Several style improvements. ... (check-in: 2318c419c9 user: stephan tags: fileedit-ajaxify) | |
|
2020-05-11
| ||
| 13:03 | Replaced the /fileedit_AJAX_ROUTE calls with /fileedit?ajax=ROUTE_NAME to eliminate the dispatch-time and help-system bloat. ... (check-in: 9f26fd1eee user: stephan tags: fileedit-ajaxify) | |
Changes
Changes to src/default_css.txt.
| ︙ | ︙ | |||
956 957 958 959 960 961 962 |
font-size: 85%;
}
body.fileedit fieldset > legend {
margin: 0 0 0 1em;
padding: 0 0.5em 0 0.5em;
}
body.fileedit fieldset > div {
| | > | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
font-size: 85%;
}
body.fileedit fieldset > legend {
margin: 0 0 0 1em;
padding: 0 0.5em 0 0.5em;
}
body.fileedit fieldset > div {
margin: 0 0.25em 0 0.25em;
padding: 0;
}
body.fileedit fieldset > div > .input-with-label {
margin: 0.25em 0.5em;
}
body.fileedit fieldset > div > button {
margin: 0.25em 0.5em;
}
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 |
overflow: auto;
white-space: pre;
}
div.fileedit-preview {
margin: 0;
padding: 0;
}
| | > | | > > > > > > > > | 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 |
overflow: auto;
white-space: pre;
}
div.fileedit-preview {
margin: 0;
padding: 0;
}
#fileedit-tab-diff-wrapper {
margin: 0;
padding: 0;
overflow: auto;
}
#fileedit-tab-preview-wrapper {
overflow: auto;
}
.fileedit-options.commit-message > div {
display: flex;
flex-direction: column;
justify-content: stretch;
font-family: monospace;
}
.fileedit-options.commit-message > div > * {
margin: 0.25em;
}
#fileedit-commit-button-wrapper {
margin: 0.25em;
}
.tab-container > .tabs > .tab-panel > .fileedit-options {
margin-top: 0;
border: none;
|
| ︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
border-style: inset;
border-radius: 0.5em;
padding: 0 0.25em;
margin: 0;
min-height: 12em;
}
#fileedit-file-selector select {
height: initial;
font-family: monospace;
}
#fileedit-file-selector select:focus {
border: none;
}
.flex-container.flex-row.stretch {
| > > > > > > > > < | > | 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 |
border-style: inset;
border-radius: 0.5em;
padding: 0 0.25em;
margin: 0;
min-height: 12em;
}
#fileedit-file-selector select {
margin: 0 0 0.5em 0;
height: initial;
font-family: monospace;
}
#fileedit-file-selector select:focus {
border: none;
}
#fileedit-file-selector > div {
padding: 0;
margin: 0;
}
#fileedit-file-selector > div > * {
margin: 0.25em 0.5em 0.25em 0;
}
.flex-container.flex-row.stretch {
flex-wrap: wrap;
align-items: baseline;
justify-content: stretch;
margin: 0;
}
.flex-container.flex-column {
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
|
| ︙ | ︙ |
Changes to src/fileedit.c.
| ︙ | ︙ | |||
1897 1898 1899 1900 1901 1902 1903 |
"Unix", 1,
"Windows", 2,
NULL);
CX("</div>"/*checkboxes*/);
}
{ /******* Commit comment, button, and result manifest *******/
| | | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 |
"Unix", 1,
"Windows", 2,
NULL);
CX("</div>"/*checkboxes*/);
}
{ /******* Commit comment, button, and result manifest *******/
CX("<fieldset class='fileedit-options commit-message'>"
"<legend>Message (required)</legend><div>\n");
/* We have two comment input fields, defaulting to single-line
** mode. JS code sets up the ability to toggle between single-
** and multi-line modes. */
CX("<input type='text' name='comment' "
"id='fileedit-comment'></input>");
CX("<textarea name='commentBig' class='hidden' "
|
| ︙ | ︙ |
Changes to src/fossil.page.fileedit.js.
1 2 3 4 5 6 7 8 9 10 11 |
(function(F/*the fossil object*/){
"use strict";
/**
Code for the /filepage app. Requires that the fossil JS
bootstrapping is complete and fossil.fetch() has been installed.
*/
const E = (s)=>document.querySelector(s),
D = F.dom,
P = F.page;
/**
| | > > > > | > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
(function(F/*the fossil object*/){
"use strict";
/**
Code for the /filepage app. Requires that the fossil JS
bootstrapping is complete and fossil.fetch() has been installed.
*/
const E = (s)=>document.querySelector(s),
D = F.dom,
P = F.page;
/**
Widget for the checkin/file selection list.
*/
P.fileSelector = {
e:{
container: E('#fileedit-file-selector')
},
finfo: {},
cache: {
checkins: undefined,
files:{}
},
/**
Fetches the list of leaf checkins from the server and updates
the UI with that list.
*/
loadLeaves: function(){
D.append(D.clearElement(
this.e.ciListLabel,
this.e.selectCi,
this.e.selectFiles
),"Loading leaves...");
D.disable(this.e.btnLoadFile, this.e.selectFiles, this.e.selectCi);
const self = this;
F.fetch('fileedit',{
urlParams:'ajax=filelist&leaves',
responseType: 'json',
onload: function(list){
D.append(D.clearElement(self.e.ciListLabel),"Open leaves:");
self.cache.checkins = list;
D.clearElement(D.enable(self.e.selectCi));
let loadThisOne;
list.forEach(function(o,n){
if(!n) loadThisOne = o;
D.option(self.e.selectCi, o.checkin,
o.timestamp+' ['+o.branch+']: '
+F.hashDigits(o.checkin));
});
self.loadFiles(loadThisOne ? loadThisOne.checkin : false);
}
});
},
/**
Loads the file list for the given checkin UUID. It uses a
cached copy on subsequent calls for the same UUID. If passed a
falsy value, it instead clears and disables the file selection
list.
*/
loadFiles: function(ciUuid){
delete this.finfo.filename;
this.finfo.checkin = ciUuid;
const selFiles = this.e.selectFiles;
if(!ciUuid){
D.clearElement(D.disable(selFiles, this.e.btnLoadFile));
return this;
|
| ︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
F.fetch('fileedit',{
urlParams:{ajax:'filelist', checkin: ciUuid},
responseType: 'json',
onload
});
return this;
},
init: function(){
const selCi = this.e.selectCi = D.select(),
selFiles = this.e.selectFiles
= D.addClass(D.select(), 'file-list'),
btnLoad = this.e.btnLoadFile =
D.addClass(D.button("Load file"), "flex-shrink"),
filesLabel = this.e.fileListLabel =
D.addClass(D.div(),'flex-shrink','file-list-label'),
ciLabel = this.e.ciListLabel =
| > > > > > > > > > > > | > | < > > > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
F.fetch('fileedit',{
urlParams:{ajax:'filelist', checkin: ciUuid},
responseType: 'json',
onload
});
return this;
},
/**
Initializes the checkin/file selector widget. Must only be
called once.
*/
init: function(){
const selCi = this.e.selectCi = D.select(),
selFiles = this.e.selectFiles
= D.addClass(D.select(), 'file-list'),
btnLoad = this.e.btnLoadFile =
D.addClass(D.button("Load file"), "flex-shrink"),
filesLabel = this.e.fileListLabel =
D.addClass(D.div(),'flex-shrink','file-list-label'),
ciLabelWrapper = D.addClass(
D.div(), 'flex-container','flex-row', 'flex-shrink',
'stretch'
),
btnReload = D.addClass(
D.button('Reload'), 'flex-shrink'
),
ciLabel = this.e.ciListLabel =
D.addClass(D.span(),'flex-shrink','checkin-list-label')
;
D.attr(selCi, 'title',"The list of opened leaves.");
D.attr(selFiles, 'title',
"The list of editable files for the selected checkin.");
D.attr(btnLoad, 'title',
"Load the selected file into the editor.");
D.disable(selCi, selFiles, btnLoad);
D.attr(selFiles, 'size', 10);
D.append(
this.e.container,
D.append(ciLabelWrapper,
btnReload, ciLabel),
selCi,
filesLabel,
selFiles,
btnLoad
);
this.loadLeaves();
selCi.addEventListener(
'change', (e)=>this.loadFiles(e.target.value), false
);
btnLoad.addEventListener(
'click', (e)=>{
this.finfo.filename = selFiles.value;
if(this.finfo.filename){
P.loadFile(this.finfo.filename, this.finfo.checkin);
}
}, false
);
btnReload.addEventListener(
'click', (e)=>this.loadLeaves(), false
);
delete this.init;
}
};
window.addEventListener("load", function() {
P.tabs = new fossil.TabManager('#fileedit-tabs');
P.e = {
|
| ︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
);
selectFontSize.dispatchEvent(
// Force UI update
new Event('change',{target:selectFontSize})
);
}
}, false)/*onload event handler*/;
/**
Toggles between single- and multi-line comment
mode.
*/
P.toggleCommentMode = function(){
var s, h, c = this.e.taComment.value;
| > > > > > > > > > > > > > > > > > > | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
);
selectFontSize.dispatchEvent(
// Force UI update
new Event('change',{target:selectFontSize})
);
}
}, false)/*onload event handler*/;
/**
Getter (if called with no args) or setter (if passed an arg) for
the current file content. We use a function, rather than direct
access so that clients can hypothetically swap out this method
from their skin in order to facilitate plugging-in of fancy
3rd-party editor widgets.
The setter form returns this object.
*/
P.value = function(){
if(0===arguments.length){
return this.e.taEditor.value;
}else{
this.e.taEditor.value = arguments[0];
return this;
}
};
/**
Toggles between single- and multi-line comment
mode.
*/
P.toggleCommentMode = function(){
var s, h, c = this.e.taComment.value;
|
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
urlParams: {
ajax: 'content',
filename:file,
checkin:rev
},
onload:(r)=>{
F.message('Loaded content.');
| | | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
urlParams: {
ajax: 'content',
filename:file,
checkin:rev
},
onload:(r)=>{
F.message('Loaded content.');
self.value(r);
self.updateVersion(file,rev);
self.tabs.switchToTab(self.e.tabs.content);
}
});
return this;
};
|
| ︙ | ︙ | |||
370 371 372 373 374 375 376 |
}
const self = this;
const updateView = function(c){
D.clearElement(f.target);
if('string'===typeof c) f.target.innerHTML = c;
if(switchToTab) self.tabs.switchToTab(self.e.tabs.preview);
};
| | | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
}
const self = this;
const updateView = function(c){
D.clearElement(f.target);
if('string'===typeof c) f.target.innerHTML = c;
if(switchToTab) self.tabs.switchToTab(self.e.tabs.preview);
};
return this._postPreview(this.value(), updateView);
};
/**
Callback for use with F.connectPagePreviewers()
*/
P._postPreview = function(content,callback){
if(!affirmHasFile()) return this;
|
| ︙ | ︙ | |||
414 415 416 417 418 419 420 |
Fetches the content diff based on the contents and settings of this
page's input fields, and updates the UI with the diff view.
Returns this object, noting that the operation is async.
*/
P.diff = function f(sbs){
if(!affirmHasFile()) return this;
| | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
Fetches the content diff based on the contents and settings of this
page's input fields, and updates the UI with the diff view.
Returns this object, noting that the operation is async.
*/
P.diff = function f(sbs){
if(!affirmHasFile()) return this;
const content = this.value(),
self = this;
if(!f.target){
f.target = this.e.tabs.diff.querySelector(
'#fileedit-tab-diff-wrapper'
);
}
const fd = new FormData();
|
| ︙ | ︙ | |||
454 455 456 457 458 459 460 |
the UI.
Returns this object.
*/
P.commit = function f(){
if(!affirmHasFile()) return this;
const self = this;
| | | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 |
the UI.
Returns this object.
*/
P.commit = function f(){
if(!affirmHasFile()) return this;
const self = this;
const content = this.value(),
target = document.querySelector('#fileedit-manifest'),
cbDryRun = E('[name=dry_run]'),
isDryRun = cbDryRun.checked,
filename = this.finfo.filename;
if(!f.updateView){
f.updateView = function(c){
target.innerHTML = [
|
| ︙ | ︙ | |||
478 479 480 481 482 483 484 |
c.dryRun ? '(dry run)' : '',
'[', F.hashDigits(c.uuid) ,'].'
];
if(!c.dryRun){
msg.push('Re-activating dry-run mode.');
self.e.taComment.value = '';
cbDryRun.checked = true;
| | > | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
c.dryRun ? '(dry run)' : '',
'[', F.hashDigits(c.uuid) ,'].'
];
if(!c.dryRun){
msg.push('Re-activating dry-run mode.');
self.e.taComment.value = '';
cbDryRun.checked = true;
self.updateVersion(filename, c.uuid);
self.fileSelector.loadLeaves();
}
F.message.apply(fossil, msg);
self.tabs.switchToTab(self.e.tabs.commit);
};
}
if(!content){
f.updateView('');
|
| ︙ | ︙ |