Completion
|
@ -53,6 +53,7 @@
|
||||||
(meta ((name "viewport") (content "width=device-width, initial-scale=1")))
|
(meta ((name "viewport") (content "width=device-width, initial-scale=1")))
|
||||||
(title ,title)
|
(title ,title)
|
||||||
(link ((rel "stylesheet") (href "/bootstrap/css/bootstrap.min.css") (type "text/css")))
|
(link ((rel "stylesheet") (href "/bootstrap/css/bootstrap.min.css") (type "text/css")))
|
||||||
|
(link ((rel "stylesheet") (href "/jquery-ui.min.css") (type "text/css")))
|
||||||
(link ((rel "stylesheet") (href "/style.css") (type "text/css")))
|
(link ((rel "stylesheet") (href "/style.css") (type "text/css")))
|
||||||
,@(for/list ((sheet (bootstrap-page-stylesheets)))
|
,@(for/list ((sheet (bootstrap-page-stylesheets)))
|
||||||
`(link ((rel "stylesheet") (href ,sheet) (type "text/css")))))
|
`(link ((rel "stylesheet") (href ,sheet) (type "text/css")))))
|
||||||
|
@ -78,6 +79,7 @@
|
||||||
|
|
||||||
(script ((type "text/javascript") (src "/jquery.min.js")))
|
(script ((type "text/javascript") (src "/jquery.min.js")))
|
||||||
(script ((type "text/javascript") (src "/jquery.tablesorter.min.js")))
|
(script ((type "text/javascript") (src "/jquery.tablesorter.min.js")))
|
||||||
|
(script ((type "text/javascript") (src "/jquery-ui.min.js")))
|
||||||
(script ((type "text/javascript") (src "/bootstrap/js/bootstrap.min.js")))
|
(script ((type "text/javascript") (src "/bootstrap/js/bootstrap.min.js")))
|
||||||
(script ((type "text/javascript") (src "/site.js")))
|
(script ((type "text/javascript") (src "/site.js")))
|
||||||
,@(for/list ((script (bootstrap-page-scripts)))
|
,@(for/list ((script (bootstrap-page-scripts)))
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
(string-trim email)))))
|
(string-trim email)))))
|
||||||
|
|
||||||
(define (gravatar-image-url email [size 80] #:extension [extension ""] #:default [default "identicon"])
|
(define (gravatar-image-url email [size 80] #:extension [extension ""] #:default [default "identicon"])
|
||||||
(format "http://www.gravatar.com/avatar/~a~a?s=~a&d=~a"
|
(format "https://www.gravatar.com/avatar/~a~a?s=~a&d=~a"
|
||||||
(gravatar-hash email)
|
(gravatar-hash email)
|
||||||
extension
|
extension
|
||||||
size
|
size
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
(require (only-in web-server/private/util exn->string))
|
(require (only-in web-server/private/util exn->string))
|
||||||
|
|
||||||
(define reload-poll-interval 0.5) ;; seconds
|
(define reload-poll-interval 0.5) ;; seconds
|
||||||
(define reload-failure-retry-delay (make-parameter 10)) ;; seconds
|
(define reload-failure-retry-delay (make-parameter 5)) ;; seconds
|
||||||
|
|
||||||
(struct entry-point (name module-path identifier-symbol [value #:mutable]) #:prefab)
|
(struct entry-point (name module-path identifier-symbol [value #:mutable]) #:prefab)
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
(hash-remove! (sessions) session-key))
|
(hash-remove! (sessions) session-key))
|
||||||
|
|
||||||
(define (lookup-session/touch! session-key)
|
(define (lookup-session/touch! session-key)
|
||||||
(log-info "Looking up session ~a" session-key)
|
|
||||||
(define s (hash-ref (sessions) session-key (lambda () #f)))
|
(define s (hash-ref (sessions) session-key (lambda () #f)))
|
||||||
(and s
|
(and s
|
||||||
(let ((s1 (struct-copy session s [expiry (+ (current-inexact-milliseconds)
|
(let ((s1 (struct-copy session s [expiry (+ (current-inexact-milliseconds)
|
||||||
|
|
20
src/site.rkt
|
@ -10,6 +10,7 @@
|
||||||
(require racket/string)
|
(require racket/string)
|
||||||
(require net/uri-codec)
|
(require net/uri-codec)
|
||||||
(require web-server/servlet)
|
(require web-server/servlet)
|
||||||
|
(require json)
|
||||||
(require "gravatar.rkt")
|
(require "gravatar.rkt")
|
||||||
(require "bootstrap.rkt")
|
(require "bootstrap.rkt")
|
||||||
(require "html-utils.rkt")
|
(require "html-utils.rkt")
|
||||||
|
@ -51,6 +52,8 @@
|
||||||
[("package" (string-arg) "edit") edit-package-page]
|
[("package" (string-arg) "edit") edit-package-page]
|
||||||
[("create") edit-package-page]
|
[("create") edit-package-page]
|
||||||
[("logout") logout-page]
|
[("logout") logout-page]
|
||||||
|
[("json" "search-completions") json-search-completions]
|
||||||
|
[("json" "all-tags") json-all-tags]
|
||||||
))
|
))
|
||||||
|
|
||||||
(define (on-continuation-expiry request)
|
(define (on-continuation-expiry request)
|
||||||
|
@ -457,7 +460,7 @@
|
||||||
|
|
||||||
(define (main-page request)
|
(define (main-page request)
|
||||||
(parameterize ((bootstrap-active-navigation nav-index)
|
(parameterize ((bootstrap-active-navigation nav-index)
|
||||||
(bootstrap-page-scripts '("/mainpage.js")))
|
(bootstrap-page-scripts '("/searchbox.js")))
|
||||||
(define package-name-list (package-search "" '((main-distribution #f))))
|
(define package-name-list (package-search "" '((main-distribution #f))))
|
||||||
(authentication-wrap
|
(authentication-wrap
|
||||||
#:request request
|
#:request request
|
||||||
|
@ -1057,7 +1060,7 @@
|
||||||
|
|
||||||
(define (search-page request)
|
(define (search-page request)
|
||||||
(parameterize ((bootstrap-active-navigation nav-search)
|
(parameterize ((bootstrap-active-navigation nav-search)
|
||||||
(bootstrap-page-scripts '("/searchpage.js")))
|
(bootstrap-page-scripts '("/searchbox.js")))
|
||||||
(authentication-wrap
|
(authentication-wrap
|
||||||
#:request request
|
#:request request
|
||||||
(define-form-bindings request ([search-text q ""]
|
(define-form-bindings request ([search-text q ""]
|
||||||
|
@ -1086,3 +1089,16 @@
|
||||||
(p ((class "package-count"))
|
(p ((class "package-count"))
|
||||||
,(format "~a packages found" (length package-name-list)))
|
,(format "~a packages found" (length package-name-list)))
|
||||||
,(package-summary-table package-name-list))))))))))
|
,(package-summary-table package-name-list))))))))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define (json-search-completions request)
|
||||||
|
(define completions (set-union (list->set (map ~a (all-package-names))) (all-tags)))
|
||||||
|
(response/output #:mime-type #"application/json"
|
||||||
|
(lambda (response-port)
|
||||||
|
(write-json (set->list completions) response-port))))
|
||||||
|
|
||||||
|
(define (json-all-tags request)
|
||||||
|
(response/output #:mime-type #"application/json"
|
||||||
|
(lambda (response-port)
|
||||||
|
(write-json (set->list (all-tags)) response-port))))
|
||||||
|
|
BIN
static/images/ui-bg_diagonals-thick_18_b81900_40x40.png
Normal file
After Width: | Height: | Size: 457 B |
BIN
static/images/ui-bg_diagonals-thick_20_666666_40x40.png
Normal file
After Width: | Height: | Size: 351 B |
BIN
static/images/ui-bg_flat_10_000000_40x100.png
Normal file
After Width: | Height: | Size: 244 B |
BIN
static/images/ui-bg_glass_100_f6f6f6_1x400.png
Normal file
After Width: | Height: | Size: 301 B |
BIN
static/images/ui-bg_glass_100_fdf5ce_1x400.png
Normal file
After Width: | Height: | Size: 387 B |
BIN
static/images/ui-bg_glass_65_ffffff_1x400.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
static/images/ui-bg_gloss-wave_35_f6a828_500x100.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Normal file
After Width: | Height: | Size: 317 B |
BIN
static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
static/images/ui-icons_222222_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
static/images/ui-icons_228ef1_256x240.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
static/images/ui-icons_ef8c08_256x240.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
static/images/ui-icons_ffd27a_256x240.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
static/images/ui-icons_ffffff_256x240.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
7
static/jquery-ui.min.css
vendored
Normal file
13
static/jquery-ui.min.js
vendored
Normal file
5
static/jquery-ui.structure.min.css
vendored
Normal file
5
static/jquery-ui.theme.min.css
vendored
Normal file
|
@ -1,3 +0,0 @@
|
||||||
$(document).ready(function () {
|
|
||||||
$("#q").focus();
|
|
||||||
});
|
|
7
static/searchbox.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
$(document).ready(function () {
|
||||||
|
$("#q").focus();
|
||||||
|
$.getJSON("/json/search-completions", function (searchCompletions) {
|
||||||
|
searchCompletions.sort();
|
||||||
|
PkgSite.multiTermComplete(PkgSite.preventTabMovingDuringSelection($("#q")), searchCompletions);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,3 +0,0 @@
|
||||||
$(document).ready(function () {
|
|
||||||
$("#q").focus();
|
|
||||||
});
|
|
|
@ -1,3 +1,43 @@
|
||||||
|
PkgSite = (function () {
|
||||||
|
function preventTabMovingDuringSelection(x) {
|
||||||
|
return x.bind("keydown", function (e) {
|
||||||
|
if (e.which === $.ui.keyCode.TAB && $(this).autocomplete("instance").menu.active) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function multiTermComplete(x, completions) {
|
||||||
|
return x.autocomplete({
|
||||||
|
source: function (req, resp) {
|
||||||
|
resp($.ui.autocomplete.filter(completions, req.term.split(/\s+/).pop()));
|
||||||
|
},
|
||||||
|
focus: function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
select: function (event, ui) {
|
||||||
|
var terms = this.value.split(/\s+/);
|
||||||
|
terms.pop();
|
||||||
|
terms.push(ui.item.value);
|
||||||
|
this.value = terms.join(" ") + " ";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
multiTermComplete: multiTermComplete,
|
||||||
|
preventTabMovingDuringSelection: preventTabMovingDuringSelection
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("table.sortable").tablesorter();
|
$("table.sortable").tablesorter();
|
||||||
|
|
||||||
|
if ($("#tags").length) {
|
||||||
|
$.getJSON("/json/all-tags", function (allTags) {
|
||||||
|
allTags.sort();
|
||||||
|
PkgSite.multiTermComplete(PkgSite.preventTabMovingDuringSelection($("#tags")), allTags);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|