source: project/stream-wiki/trunk/extensions/progress.scm @ 4923

Last change on this file since 4923 was 4923, checked in by azul, 12 years ago

Fixes.

File size: 9.6 KB
Line 
1(use html-stream stream-ext srfi-40)
2
3(define-syntax environment
4  (syntax-rules ()
5    ((environment original ((name expr) ...))
6     (lambda (op)
7       (case op
8         ((name) expr)
9         ...
10         (else (original op)))))
11    ((environment ((name expr) ...))
12     (environment (lambda (op)
13                    (warning "unbound variable (dynamic environment)" op)
14                    (if #f #f))
15                  ((name expr) ...)))))
16
17(define-syntax environment-get
18  (syntax-rules ()
19    ((environment-get env sym) (env 'sym))))
20
21(define-syntax let-from-environment
22  (syntax-rules ()
23    ((let-from-environment env (sym ...) body ...)
24     (let ((sym (environment-get env sym)) ...) body ...))))
25
26(define-syntax environment-capture
27  (syntax-rules ()
28    ((environment-capture env (sym ...))
29     (environment env ((sym sym) ...)))
30    ((environment-capture (sym ...))
31     (environment ((sym sym) ...)))))
32
33(define *progress-js-code*
34  #<<EOJS
35if (typeof(svnwikiProgress) != "object") {
36
37var svnwikiProgress = new Object();
38
39// We use this to avoid the GC from collecting objects from loadXml before
40// they have actually loaded their documents and processed them:
41
42svnwikiProgress.requests = new Array();
43
44svnwikiProgress.loadXml = function (href, process)
45{
46  var xmlDoc;
47  var len = svnwikiProgress.requests.length;
48
49  if (document.implementation && document.implementation.createDocument)
50    {
51      xmlDoc = document.implementation.createDocument("", "", null);
52      xmlDoc.onload = function () { svnwikiProgress.removeRequest(xmlDoc); process(xmlDoc) };
53    }
54  else if (window.ActiveXObject)
55    {
56      xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
57      xmlDoc.onreadystatechange = function () { if (xmlDoc.readyState == 4) { svnwikiProgress.removeRequest(xmlDoc); process(xmlDoc); } };
58    }
59  else
60    {
61      alert('Your browser can\'t handle this script');
62      return;
63    }
64
65  svnwikiProgress.requests.push(xmlDoc);
66  xmlDoc.load(href);
67}
68
69svnwikiProgress.removeRequest = function (element)
70{
71  var rd, wr;
72  for (rd = 0, wr = 0; rd < svnwikiProgress.requests.length; rd ++)
73    if (svnwikiProgress.requests[rd] != element)
74      svnwikiProgress.requests[wr ++] = svnwikiProgress.requests[rd];
75  while (wr < svnwikiProgress.requests.len)
76    svnwikiProgress.requests.pop();
77}
78
79svnwikiProgress.cleanContent = function (element)
80{
81  while (element.hasChildNodes())
82    element.removeChild(element.firstChild);
83}
84
85svnwikiProgress.makeLink = function ( target, content )
86{
87  var link = svnwikiProgress.makeElement('A', content);
88  link.setAttribute('href', target);
89  return link;
90}
91
92svnwikiProgress.makeElement = function ( type, content )
93{
94  var elem = document.createElement(type);
95  if (content)
96    elem.appendChild(content);
97  return elem;
98}
99
100svnwikiProgress.init = function ( expectedRev, target, staticURL )
101{
102  svnwikiProgress.loading = true;
103  svnwikiProgress.delay = 1000;
104  svnwikiProgress.expectedRev = expectedRev;
105  svnwikiProgress.position = 0;
106  svnwikiProgress.actualTime = 0;
107  // Append some random string at the end of the URL to defeat caches:
108  svnwikiProgress.staticURL = staticURL + "?" + expectedRev;
109
110  svnwikiProgress.progressWidget = document.getElementById(target);
111
112  for (var j = 0; j <= 8; ++j) {
113    if (j == 0 || j == 3 || j == 6) {
114      var span = svnwikiProgress.makeElement('span');
115      span.setAttribute('class', 'progress-break');
116      svnwikiProgress.progressWidget.appendChild(span);
117    }
118    var span = svnwikiProgress.makeElement('span');
119    span.setAttribute('class', 'progress-entry');
120    span.setAttribute('id', 'progress-id-' + j);
121    svnwikiProgress.progressWidget.appendChild(span);
122  }
123
124  svnwikiProgress.statusBar = svnwikiProgress.makeElement('p');
125  svnwikiProgress.progressWidget.appendChild(svnwikiProgress.statusBar);
126  svnwikiProgress.advance("Checking status...");
127  svnwikiProgress.checkProgress();
128}
129
130svnwikiProgress.advance = function ( text )
131{
132  svnwikiProgress.showWaitText(text);
133
134  if (!svnwikiProgress.loading) {
135    svnwikiProgress.progressWidget.style.display = "none";
136    return;
137  }
138
139  var colors = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
140  var chars = [ "0", "2", "4", "6", "8", "a", "c", "e" ];
141
142  svnwikiProgress.position = (svnwikiProgress.position + 1) % colors.length;
143
144  var current = chars.length;
145
146  for (var j = 0; j < 8; j ++) {
147    colors[(svnwikiProgress.position + j) % colors.length] = current;
148    current --;
149  }
150
151  for (var j = 0; j < colors.length; j ++) {
152    var position = document.getElementById("progress-id-" + j);
153    if (!position)
154      alert("Failed for" + j + ":" + colors.length);
155    position.setAttribute('style', 'background: #' + chars[colors[j]] + chars[colors[j]] + 'f;');
156  }
157}
158
159svnwikiProgress.showWaitText = function ( text )
160{
161  svnwikiProgress.cleanContent(svnwikiProgress.statusBar);
162  svnwikiProgress.statusBar.appendChild(document.createTextNode(svnwikiProgress.loading ? text : 'Done'));
163}
164
165svnwikiProgress.redirectStart = function ( )
166{
167  svnwikiProgress.cleanContent(svnwikiProgress.showTime);
168  if (svnwikiProgress.redirectTime == 0) {
169    svnwikiProgress.showTime.appendChild(document.createTextNode('You are now being redirected to '));
170    svnwikiProgress.showTime.appendChild(svnwikiProgress.makeLink(svnwikiProgress.staticURL, document.createTextNode('the resulting page')));
171    svnwikiProgress.showTime.appendChild(document.createTextNode('.'));
172    window.location = svnwikiProgress.staticURL;
173    return;
174  }
175
176  svnwikiProgress.showTime.appendChild(document.createTextNode('You will be redirected to '));
177  svnwikiProgress.showTime.appendChild(svnwikiProgress.makeLink(svnwikiProgress.staticURL, document.createTextNode('the resulting page')));
178  svnwikiProgress.showTime.appendChild(document.createTextNode(' in ' + svnwikiProgress.redirectTime + ' ' + (svnwikiProgress.redirectTime == 1 ? 'second' : 'seconds') + '.'));
179  setTimeout("svnwikiProgress.redirectStart();", 1000);
180  svnwikiProgress.redirectTime --;
181}
182
183svnwikiProgress.registerProgress = function ( xmlDoc )
184{
185  if (svnwikiProgress.expectedRev > -1
186      && xmlDoc.getElementsByTagName('rev')[0].childNodes[0].nodeValue >= svnwikiProgress.expectedRev) {
187    svnwikiProgress.loading = false;
188  }
189
190  svnwikiProgress.advance(xmlDoc.getElementsByTagName('desc')[0].childNodes[0].nodeValue);
191
192  if (!svnwikiProgress.loading) {
193    svnwikiProgress.redirectTime = 5;
194    var report = document.getElementById('progress-commit-message');
195    if (report) {
196      svnwikiProgress.cleanContent(report);
197      report.appendChild(svnwikiProgress.makeElement('p', svnwikiProgress.makeElement('b', document.createTextNode('Your changes have been saved.'))));
198      svnwikiProgress.showTime = svnwikiProgress.makeElement('p');
199      report.appendChild(svnwikiProgress.showTime);
200      svnwikiProgress.redirectStart();
201    }
202    return;
203  }
204
205  var actualTime = xmlDoc.getElementsByTagName('time')[0].childNodes[0].nodeValue;
206  if (actualTime != svnwikiProgress.actualTime) {
207    svnwikiProgress.actualTime = actualTime;
208    svnwikiProgress.delay = 1000;
209  } else if (svnwikiProgress.delay < 120000) {
210    svnwikiProgress.delay *= 1.5;
211  }
212
213  setTimeout("svnwikiProgress.checkProgress()", svnwikiProgress.delay);
214}
215
216svnwikiProgress.checkProgress = function ( )
217{
218  svnwikiProgress.loadXml('?action=progress', svnwikiProgress.registerProgress);
219}
220
221}
222EOJS
223)
224
225(define (progress-code-write env)
226  (let-from-environment env (path-out program)
227    (when (and path-out (string=? program "post-commit"))
228      (assert (and 'progress-code-write (string? path-out)))
229      (unless (directory? (svnwiki-make-pathname path-out "xsvnwiki-helper"))
230        (create-directory (svnwiki-make-pathname path-out "xsvnwiki-helper")))
231      (unless (directory? (svnwiki-make-pathname (list path-out "xsvnwiki-helper") "progress"))
232        (create-directory (svnwiki-make-pathname (list path-out "xsvnwiki-helper") "progress")))
233      (write-file-with-tmp
234        (svnwiki-make-pathname (list "xsvnwiki-helper" "progress") "progress")
235        "text/javascript"
236        path-out
237        (string->stream
238          *progress-js-code*)))))
239
240(define (progress-commit-dynamic env)
241  (->stream-char
242    "Content-type: text/html\n\n"
243    (html-stream
244      (html
245        (body
246          (progress-commit-code (environment env ((commit-rev -1)))))))))
247
248(define (progress-commit-code env)
249  (let-from-environment env (static-url commit-rev path)
250    (html-stream
251      ((div id "progress-commit-confirmation"))
252      ((script type "text/javascript" src (format #f "~A/xsvnwiki-helper/progress/progress" static-url)))
253      ((script type "text/javascript")
254       (format #f "<!--~%if (typeof(svnwikiProgress) == 'object' && typeof(svnwikiProgress.init) == 'function') { svnwikiProgress.init(~A, 'progress-commit-confirmation', '~A/~A'); }~%-->"
255               commit-rev
256               static-url
257               path)))))
258
259(define (progress-commit-confirmation env)
260  (let-from-environment env (path)
261    (svnwiki-render-commit-confirmation
262      env
263      (html-stream
264        ((div id "progress-commit-message")
265         (p (b "Your changes have been saved."))
266         (p "The wiki system is preparing to display your changes.  While waiting, you could:")
267         (ul
268           (li ((a href (last (string-split (environment-get env path) "/"))) "Go to the " (b "currently published revision") " of the file") " (which probably won't reflect your changes yet).")
269           (li ((a href (format #f "~A?action=edit" (last (string-split path "/")))) "Go back to the " (b "edit form") " and continue making changes") ".")))
270        (progress-commit-code env)))))
271
272(set! *extensions*
273  `((progress (commit-confirmation ,progress-commit-confirmation)
274              (update ,progress-code-write)
275              (dynamic ,progress-commit-dynamic))))
Note: See TracBrowser for help on using the repository browser.