Commit 0872e2c7ddfcf00943ad73992322244ce3c8ef30

Authored by Tiago Bortoletto Vaz
1 parent 3b065dde
Exists in master and in 1 other branch add_vagrant

New layout, getting DDE/UDD data

README
1 1 AppRecommender - Application recommender for GNU/Linux systems
2 2  
3   -Depends: python debian-python apt-xapian-index python-stats python-webpy python-cluster
  3 +Depends: python debian-python apt-xapian-index python-stats python-webpy python-cluster python-simplejson
4 4  
5 5 More info: https://github.com/tassia/AppRecommender/wiki
... ...
src/web/server.py
... ... @@ -4,6 +4,7 @@ import web
4 4 from web import form
5 5 import tempfile
6 6 import sys
  7 +import simplejson as json
7 8  
8 9 sys.path.insert(0,"../")
9 10  
... ... @@ -11,6 +12,8 @@ from config import *
11 12 from recommender import *
12 13 from user import *
13 14  
  15 +import urllib
  16 +
14 17 class RequestForm(form.Form):
15 18 def __init__(self):
16 19 form.Form.__init__(self, \
... ... @@ -54,6 +57,41 @@ class Thanks:
54 57 def POST(self):
55 58 return render.thanks()
56 59  
  60 +class Package:
  61 + def GET(self, pkg):
  62 + json_source = "http://dde.debian.net/dde/q/udd/packages/all/%s?t=json" % pkg #FIXME: go to config
  63 + json_data = json.load(urllib.urlopen(json_source))
  64 + tags = debtags_list_to_dict(json_data['r']['tag'])
  65 + json_data['r']['tag'] = tags
  66 + return render_plain.package(json_data['r'])
  67 +
  68 +def debtags_list_to_dict(debtags_list):
  69 + """ in:
  70 + ['use::editing',
  71 + 'works-with-format::gif',
  72 + 'works-with-format::jpg',
  73 + 'works-with-format::pdf']
  74 + out:
  75 + {'use': [editing],
  76 + 'works-with-format': ['gif', 'jpg', 'pdf']'
  77 + }
  78 + """
  79 + debtags = {}
  80 + subtags = []
  81 + for tag in debtags_list:
  82 + match = re.search(r'^(.*)::(.*)$', tag)
  83 + if not match:
  84 + log.error("Could not parse debtags format from tag: %s", tag)
  85 + facet, subtag = match.groups()
  86 + subtags.append(subtag)
  87 + if facet not in debtags:
  88 + debtags[facet] = subtags
  89 + else:
  90 + debtags[facet].append(subtag)
  91 + subtags = []
  92 + return debtags
  93 +
  94 +
57 95 class AppRecommender:
58 96 def POST(self):
59 97 outputdir = tempfile.mkdtemp(prefix='',dir='./submissions/')
... ... @@ -91,11 +129,25 @@ class AppRecommender:
91 129 strategies.append("hybrid")
92 130 if request_info.has_key('strategy_hybrid_plus'):
93 131 strategies.append("hybrid_plus")
94   -
95   - return render.apprec("/thanks", "post",
96   - self._recommends(user_id,user_pkgs_list,
97   - strategies, int(request_info['limit'])),
98   - FeedbackForm(strategies))
  132 + recommends = self._recommends(user_id,user_pkgs_list,strategies, int(request_info['limit']))
  133 + return render.apprec("/thanks", "post", recommends, FeedbackForm(strategies))
  134 +
  135 +# parsing json from screenshots - can be usefull in the future...
  136 +# def _packages_attrs(self, recommends): #recommends is result of _recommends()
  137 +# all_recommended_packages = []
  138 +# recommended_pkgs_attrs = {}
  139 +# json_file_path = 'static/json/screenshots.json' #FIXME: go to config file
  140 +# json_file = open(json_file_path)
  141 +# json_data = json.load(json_file)
  142 +# for strategy, result in recommends.items():
  143 +# all_recommended_packages.extend(result)
  144 +# for pkg_attrs_dict in json_data['screenshots']:
  145 +# if pkg_attrs_dict['name'] in all_recommended_packages:
  146 +# recommended_pkgs_attrs[pkg_attrs_dict['name']] = pkg_attrs_dict
  147 +# return recommended_pkgs_attrs
  148 +
  149 + def _get_pkg_attrs(self, pkg_name):
  150 + pass
99 151  
100 152 def _recommends(self,user_id,user_pkgs_list,strategies,limit):
101 153 user = User(dict.fromkeys(user_pkgs_list,1),user_id)
... ... @@ -120,10 +172,12 @@ def add_global_hook():
120 172 return _wrapper
121 173  
122 174 render = web.template.render('templates/', base='layout')
  175 +render_plain = web.template.render('templates/')
123 176  
124   -urls = ('/', 'Index',
125   - '/apprec', 'AppRecommender',
126   - '/thanks', 'Thanks'
  177 +urls = ('/', 'Index',
  178 + '/apprec', 'AppRecommender',
  179 + '/thanks', 'Thanks',
  180 + '/package/(.*)', 'Package'
127 181 )
128 182  
129 183 web.webapi.internalerror = web.debugerror
... ...
src/web/static/css/style.css
... ... @@ -51,8 +51,8 @@ body {
51 51  
52 52 td {
53 53 border: 1px solid #d0d0d0;
54   - padding: 2px 2px;
55 54 vertical-align: top;
  55 + padding: 2px 2px;
56 56 }
57 57  
58 58 td.noborder {
... ... @@ -468,7 +468,7 @@ div.jGrowl div.jGrowl-closer {
468 468 margin-bottom: 10px;
469 469 }
470 470  
471   -.imgcaption .smaller {
  471 +.smaller {
472 472 font-size: 80%;
473 473 }
474 474  
... ...
src/web/static/css/thickbox.css 0 → 100644
... ... @@ -0,0 +1,163 @@
  1 +/* ----------------------------------------------------------------------------------------------------------------*/
  2 +/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/
  3 +/* ----------------------------------------------------------------------------------------------------------------*/
  4 +*{padding: 0; margin: 0;}
  5 +
  6 +/* ----------------------------------------------------------------------------------------------------------------*/
  7 +/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/
  8 +/* ----------------------------------------------------------------------------------------------------------------*/
  9 +#TB_window {
  10 + font: 12px Arial, Helvetica, sans-serif;
  11 + color: #333333;
  12 +}
  13 +
  14 +#TB_secondLine {
  15 + font: 10px Arial, Helvetica, sans-serif;
  16 + color:#666666;
  17 +}
  18 +
  19 +#TB_window a:link {color: #666666;}
  20 +#TB_window a:visited {color: #666666;}
  21 +#TB_window a:hover {color: #000;}
  22 +#TB_window a:active {color: #666666;}
  23 +#TB_window a:focus{color: #666666;}
  24 +
  25 +/* ----------------------------------------------------------------------------------------------------------------*/
  26 +/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/
  27 +/* ----------------------------------------------------------------------------------------------------------------*/
  28 +#TB_overlay {
  29 + position: fixed;
  30 + z-index:100;
  31 + top: 0px;
  32 + left: 0px;
  33 + height:100%;
  34 + width:100%;
  35 +}
  36 +
  37 +.TB_overlayMacFFBGHack {background: url(/static/images/macFFBgHack.png) repeat;}
  38 +.TB_overlayBG {
  39 + background-color:#000;
  40 + filter:alpha(opacity=75);
  41 + -moz-opacity: 0.75;
  42 + opacity: 0.75;
  43 +}
  44 +
  45 +* html #TB_overlay { /* ie6 hack */
  46 + position: absolute;
  47 + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
  48 +}
  49 +
  50 +#TB_window {
  51 + position: fixed;
  52 + background: #ffffff;
  53 + z-index: 102;
  54 + color:#000000;
  55 + display:none;
  56 + border: 4px solid #525252;
  57 + text-align:left;
  58 + top:50%;
  59 + left:50%;
  60 +}
  61 +
  62 +* html #TB_window { /* ie6 hack */
  63 +position: absolute;
  64 +margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
  65 +}
  66 +
  67 +#TB_window img#TB_Image {
  68 + display:block;
  69 + margin: 15px 0 0 15px;
  70 + border-right: 1px solid #ccc;
  71 + border-bottom: 1px solid #ccc;
  72 + border-top: 1px solid #666;
  73 + border-left: 1px solid #666;
  74 +}
  75 +
  76 +#TB_caption{
  77 + height:25px;
  78 + padding:7px 30px 10px 25px;
  79 + float:left;
  80 +}
  81 +
  82 +#TB_closeWindow{
  83 + height:25px;
  84 + padding:11px 25px 10px 0;
  85 + float:right;
  86 +}
  87 +
  88 +#TB_closeAjaxWindow{
  89 + padding:7px 10px 5px 0;
  90 + margin-bottom:1px;
  91 + text-align:right;
  92 + float:right;
  93 +}
  94 +
  95 +#TB_ajaxWindowTitle{
  96 + float:left;
  97 + padding:7px 0 5px 10px;
  98 + margin-bottom:1px;
  99 +}
  100 +
  101 +#TB_title{
  102 + background-color:#e8e8e8;
  103 + height:27px;
  104 +}
  105 +
  106 +#TB_ajaxContent{
  107 + clear:both;
  108 + padding:2px 15px 15px 15px;
  109 + overflow:auto;
  110 + text-align:left;
  111 + line-height:1.4em;
  112 +}
  113 +
  114 +#TB_ajaxContent.TB_modal{
  115 + padding:15px;
  116 +}
  117 +
  118 +#TB_ajaxContent p{
  119 + padding:5px 0px 5px 0px;
  120 +}
  121 +
  122 +#TB_load{
  123 + position: fixed;
  124 + display:none;
  125 + height:13px;
  126 + width:208px;
  127 + z-index:103;
  128 + top: 50%;
  129 + left: 50%;
  130 + margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */
  131 +}
  132 +
  133 +* html #TB_load { /* ie6 hack */
  134 +position: absolute;
  135 +margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
  136 +}
  137 +
  138 +#TB_HideSelect{
  139 + z-index:99;
  140 + position:fixed;
  141 + top: 0;
  142 + left: 0;
  143 + background-color:#fff;
  144 + border:none;
  145 + filter:alpha(opacity=0);
  146 + -moz-opacity: 0;
  147 + opacity: 0;
  148 + height:100%;
  149 + width:100%;
  150 +}
  151 +
  152 +* html #TB_HideSelect { /* ie6 hack */
  153 + position: absolute;
  154 + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
  155 +}
  156 +
  157 +#TB_iframeContent{
  158 + clear:both;
  159 + border:none;
  160 + margin-bottom:-1px;
  161 + margin-top:1px;
  162 + _margin-bottom:1px;
  163 +}
... ...
src/web/static/images/loadingAnimation.gif 0 → 100644

5.75 KB

src/web/static/js/thickbox.js 0 → 100644
... ... @@ -0,0 +1,319 @@
  1 +/*
  2 + * Thickbox 3.1 - One Box To Rule Them All.
  3 + * By Cody Lindley (http://www.codylindley.com)
  4 + * Copyright (c) 2007 cody lindley
  5 + * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
  6 +*/
  7 +
  8 +var tb_pathToImage = "/static/images/loadingAnimation.gif";
  9 +
  10 +/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/
  11 +
  12 +//on page load call tb_init
  13 +$(document).ready(function(){
  14 + tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox
  15 + imgLoader = new Image();// preload image
  16 + imgLoader.src = tb_pathToImage;
  17 +});
  18 +
  19 +//add thickbox to href & area elements that have a class of .thickbox
  20 +function tb_init(domChunk){
  21 + $(domChunk).click(function(){
  22 + var t = this.title || this.name || null;
  23 + var a = this.href || this.alt;
  24 + var g = this.rel || false;
  25 + tb_show(t,a,g);
  26 + this.blur();
  27 + return false;
  28 + });
  29 +}
  30 +
  31 +function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link
  32 +
  33 + try {
  34 + if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
  35 + $("body","html").css({height: "100%", width: "100%"});
  36 + $("html").css("overflow","hidden");
  37 + if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
  38 + $("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
  39 + $("#TB_overlay").click(tb_remove);
  40 + }
  41 + }else{//all others
  42 + if(document.getElementById("TB_overlay") === null){
  43 + $("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");
  44 + $("#TB_overlay").click(tb_remove);
  45 + }
  46 + }
  47 +
  48 + if(tb_detectMacXFF()){
  49 + $("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash
  50 + }else{
  51 + $("#TB_overlay").addClass("TB_overlayBG");//use background and opacity
  52 + }
  53 +
  54 + if(caption===null){caption="";}
  55 + $("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
  56 + $('#TB_load').show();//show loader
  57 +
  58 + var baseURL;
  59 + if(url.indexOf("?")!==-1){ //ff there is a query string involved
  60 + baseURL = url.substr(0, url.indexOf("?"));
  61 + }else{
  62 + baseURL = url;
  63 + }
  64 +
  65 + var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
  66 + var urlType = baseURL.toLowerCase().match(urlString);
  67 +
  68 + if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images
  69 +
  70 + TB_PrevCaption = "";
  71 + TB_PrevURL = "";
  72 + TB_PrevHTML = "";
  73 + TB_NextCaption = "";
  74 + TB_NextURL = "";
  75 + TB_NextHTML = "";
  76 + TB_imageCount = "";
  77 + TB_FoundURL = false;
  78 + if(imageGroup){
  79 + TB_TempArray = $("a[@rel="+imageGroup+"]").get();
  80 + for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
  81 + var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
  82 + if (!(TB_TempArray[TB_Counter].href == url)) {
  83 + if (TB_FoundURL) {
  84 + TB_NextCaption = TB_TempArray[TB_Counter].title;
  85 + TB_NextURL = TB_TempArray[TB_Counter].href;
  86 + TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";
  87 + } else {
  88 + TB_PrevCaption = TB_TempArray[TB_Counter].title;
  89 + TB_PrevURL = TB_TempArray[TB_Counter].href;
  90 + TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";
  91 + }
  92 + } else {
  93 + TB_FoundURL = true;
  94 + TB_imageCount = "Image " + (TB_Counter + 1) +" of "+ (TB_TempArray.length);
  95 + }
  96 + }
  97 + }
  98 +
  99 + imgPreloader = new Image();
  100 + imgPreloader.onload = function(){
  101 + imgPreloader.onload = null;
  102 +
  103 + // Resizing large images - orginal by Christian Montoya edited by me.
  104 + var pagesize = tb_getPageSize();
  105 + var x = pagesize[0] - 150;
  106 + var y = pagesize[1] - 150;
  107 + var imageWidth = imgPreloader.width;
  108 + var imageHeight = imgPreloader.height;
  109 + if (imageWidth > x) {
  110 + imageHeight = imageHeight * (x / imageWidth);
  111 + imageWidth = x;
  112 + if (imageHeight > y) {
  113 + imageWidth = imageWidth * (y / imageHeight);
  114 + imageHeight = y;
  115 + }
  116 + } else if (imageHeight > y) {
  117 + imageWidth = imageWidth * (y / imageHeight);
  118 + imageHeight = y;
  119 + if (imageWidth > x) {
  120 + imageHeight = imageHeight * (x / imageWidth);
  121 + imageWidth = x;
  122 + }
  123 + }
  124 + // End Resizing
  125 +
  126 + TB_WIDTH = imageWidth + 30;
  127 + TB_HEIGHT = imageHeight + 60;
  128 + $("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div>");
  129 +
  130 + $("#TB_closeWindowButton").click(tb_remove);
  131 +
  132 + if (!(TB_PrevHTML === "")) {
  133 + function goPrev(){
  134 + if($(document).unbind("click",goPrev)){$(document).unbind("click",goPrev);}
  135 + $("#TB_window").remove();
  136 + $("body").append("<div id='TB_window'></div>");
  137 + tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
  138 + return false;
  139 + }
  140 + $("#TB_prev").click(goPrev);
  141 + }
  142 +
  143 + if (!(TB_NextHTML === "")) {
  144 + function goNext(){
  145 + $("#TB_window").remove();
  146 + $("body").append("<div id='TB_window'></div>");
  147 + tb_show(TB_NextCaption, TB_NextURL, imageGroup);
  148 + return false;
  149 + }
  150 + $("#TB_next").click(goNext);
  151 +
  152 + }
  153 +
  154 + document.onkeydown = function(e){
  155 + if (e == null) { // ie
  156 + keycode = event.keyCode;
  157 + } else { // mozilla
  158 + keycode = e.which;
  159 + }
  160 + if(keycode == 27){ // close
  161 + tb_remove();
  162 + } else if(keycode == 190){ // display previous image
  163 + if(!(TB_NextHTML == "")){
  164 + document.onkeydown = "";
  165 + goNext();
  166 + }
  167 + } else if(keycode == 188){ // display next image
  168 + if(!(TB_PrevHTML == "")){
  169 + document.onkeydown = "";
  170 + goPrev();
  171 + }
  172 + }
  173 + };
  174 +
  175 + tb_position();
  176 + $("#TB_load").remove();
  177 + $("#TB_ImageOff").click(tb_remove);
  178 + $("#TB_window").css({display:"block"}); //for safari using css instead of show
  179 + };
  180 +
  181 + imgPreloader.src = url;
  182 + }else{//code to show html
  183 +
  184 + var queryString = url.replace(/^[^\?]+\??/,'');
  185 + var params = tb_parseQuery( queryString );
  186 +
  187 + TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
  188 + TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL
  189 + ajaxContentW = TB_WIDTH - 30;
  190 + ajaxContentH = TB_HEIGHT - 45;
  191 +
  192 + if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window
  193 + urlNoQuery = url.split('TB_');
  194 + $("#TB_iframeContent").remove();
  195 + if(params['modal'] != "true"){//iframe no modal
  196 + $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;' > </iframe>");
  197 + }else{//iframe modal
  198 + $("#TB_overlay").unbind();
  199 + $("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");
  200 + }
  201 + }else{// not an iframe, ajax
  202 + if($("#TB_window").css("display") != "block"){
  203 + if(params['modal'] != "true"){//ajax no modal
  204 + $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'>close</a> or Esc Key</div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");
  205 + }else{//ajax modal
  206 + $("#TB_overlay").unbind();
  207 + $("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");
  208 + }
  209 + }else{//this means the window is already up, we are just loading new content via ajax
  210 + $("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";
  211 + $("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";
  212 + $("#TB_ajaxContent")[0].scrollTop = 0;
  213 + $("#TB_ajaxWindowTitle").html(caption);
  214 + }
  215 + }
  216 +
  217 + $("#TB_closeWindowButton").click(tb_remove);
  218 +
  219 + if(url.indexOf('TB_inline') != -1){
  220 + $("#TB_ajaxContent").append($('#' + params['inlineId']).children());
  221 + $("#TB_window").unload(function () {
  222 + $('#' + params['inlineId']).append( $("#TB_ajaxContent").children() ); // move elements back when you're finished
  223 + });
  224 + tb_position();
  225 + $("#TB_load").remove();
  226 + $("#TB_window").css({display:"block"});
  227 + }else if(url.indexOf('TB_iframe') != -1){
  228 + tb_position();
  229 + if($.browser.safari){//safari needs help because it will not fire iframe onload
  230 + $("#TB_load").remove();
  231 + $("#TB_window").css({display:"block"});
  232 + }
  233 + }else{
  234 + $("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method
  235 + tb_position();
  236 + $("#TB_load").remove();
  237 + tb_init("#TB_ajaxContent a.thickbox");
  238 + $("#TB_window").css({display:"block"});
  239 + });
  240 + }
  241 +
  242 + }
  243 +
  244 + if(!params['modal']){
  245 + document.onkeyup = function(e){
  246 + if (e == null) { // ie
  247 + keycode = event.keyCode;
  248 + } else { // mozilla
  249 + keycode = e.which;
  250 + }
  251 + if(keycode == 27){ // close
  252 + tb_remove();
  253 + }
  254 + };
  255 + }
  256 +
  257 + } catch(e) {
  258 + //nothing here
  259 + }
  260 +}
  261 +
  262 +//helper functions below
  263 +function tb_showIframe(){
  264 + $("#TB_load").remove();
  265 + $("#TB_window").css({display:"block"});
  266 +}
  267 +
  268 +function tb_remove() {
  269 + $("#TB_imageOff").unbind("click");
  270 + $("#TB_closeWindowButton").unbind("click");
  271 + $("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
  272 + $("#TB_load").remove();
  273 + if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
  274 + $("body","html").css({height: "auto", width: "auto"});
  275 + $("html").css("overflow","");
  276 + }
  277 + document.onkeydown = "";
  278 + document.onkeyup = "";
  279 + return false;
  280 +}
  281 +
  282 +function tb_position() {
  283 +$("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});
  284 + if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
  285 + $("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
  286 + }
  287 +}
  288 +
  289 +function tb_parseQuery ( query ) {
  290 + var Params = {};
  291 + if ( ! query ) {return Params;}// return empty object
  292 + var Pairs = query.split(/[;&]/);
  293 + for ( var i = 0; i < Pairs.length; i++ ) {
  294 + var KeyVal = Pairs[i].split('=');
  295 + if ( ! KeyVal || KeyVal.length != 2 ) {continue;}
  296 + var key = unescape( KeyVal[0] );
  297 + var val = unescape( KeyVal[1] );
  298 + val = val.replace(/\+/g, ' ');
  299 + Params[key] = val;
  300 + }
  301 + return Params;
  302 +}
  303 +
  304 +function tb_getPageSize(){
  305 + var de = document.documentElement;
  306 + var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
  307 + var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
  308 + arrayPageSize = [w,h];
  309 + return arrayPageSize;
  310 +}
  311 +
  312 +function tb_detectMacXFF() {
  313 + var userAgent = navigator.userAgent.toLowerCase();
  314 + if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
  315 + return true;
  316 + }
  317 +}
  318 +
  319 +
... ...
src/web/templates/apprec.html
... ... @@ -10,7 +10,6 @@ $$(document).ready(function() {
10 10 });
11 11 </script>
12 12  
13   -
14 13 <div class="graybox">
15 14 <h1>Results per strategy</h1>
16 15 <ul class="toc">
... ... @@ -29,18 +28,17 @@ $for strategy, result in recommends.items():
29 28 $for pkg in result:
30 29 $ count = count + 1
31 30 <td style="text-align: center; border: 4px solid rgb(255, 255, 255); min-width: 160px;">
32   - <input type="checkbox" value="$pkg">
33   - <b>$pkg </b>
34   - <div class="screenshots cycle" style="height: 120px">
35   - <a class="image" href="http://screenshots.debian.net/screenshot/$pkg" title="Screenshot of package $pkg">
36   - <img src="http://screenshots.debian.net/thumbnail/$pkg" alt="Screenshot">
37   - </a>
38   - </div>
39   - <div class="imgcaption">
40   - <a href="http://screenshots.debian.net/package/$pkg">
41   - <span class="smaller">short description</span>
42   - </a>
43   - </div>
  31 + <p><a href="package/$pkg?height=350&width=500" class="thickbox" title="General information for package $pkg"><b>$pkg</b></a></p>
  32 + <div class="screenshots cycle" style="height: 120px">
  33 + <a class="image" href="http://screenshots.debian.net/screenshot/$pkg" title="Screenshot of package $pkg">
  34 + <img src="http://screenshots.debian.net/thumbnail/$pkg" alt="Screenshot">
  35 + </a>
  36 + </div>
  37 +
  38 + <div class="imgcaption">
  39 + <a href="http://screenshots.debian.net/package/$pkg">
  40 + <p class="smaller">short description</p>
  41 + </div>
44 42 </td>
45 43 $if count == 5:
46 44 $ count = 0
... ...
src/web/templates/layout.html
... ... @@ -10,6 +10,7 @@ $ url_base = &quot;http://localhost:8080/&quot;
10 10  
11 11 <link href="/static/css/style.css" media="screen" rel="stylesheet" type="text/css" />
12 12 <link href="/static/css/local.css" media="screen" rel="stylesheet" type="text/css" />
  13 + <link href="/static/css/thickbox.css" media="screen" rel="stylesheet" type="text/css" />
13 14  
14 15 <script src="/static/js/jquery.js" type="text/javascript"></script>
15 16 <script src="/static/js/jquery.autocomplete.js" type="text/javascript"></script>
... ... @@ -18,6 +19,30 @@ $ url_base = &quot;http://localhost:8080/&quot;
18 19 <script src="/static/js/jquery.tooltip.js" type="text/javascript"></script>
19 20 <script src="/static/js/jquery.cycle.js" type="text/javascript"></script>
20 21 <script src="/static/js/handlers.js" type="text/javascript"></script>
  22 + <script src="/static/js/local.js" type="text/javascript"></script>
  23 +
  24 + <script type="text/javascript" src="/static/js/thickbox.js"></script>
  25 +
  26 +<!--
  27 + <link rel="stylesheet" href="/static/cluetip/jquery.cluetip.css" type="text/css" />
  28 +
  29 + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script>
  30 + <script src="/static/cluetip/lib/jquery.hoverIntent.js" type="text/javascript"></script>
  31 + <script src="/static/cluetip/lib/jquery.bgiframe.min.js" type="text/javascript"></script>
  32 + <script src="/static/cluetip/jquery.cluetip.js" type="text/javascript"></script>
  33 +
  34 + <script type="text/javascript">
  35 + $$(document).ready(function() {
  36 + $$('a.tips').cluetip();
  37 +
  38 + $$('#houdini').cluetip({
  39 + splitTitle: '|', // use the invoking element's title attribute to populate the clueTip...
  40 + // ...and split the contents into separate divs where there is a "|"
  41 + showTitle: false // hide the clueTip's heading
  42 + });
  43 + });
  44 + </script>
  45 +-->
21 46  
22 47 <link rel="shortcut icon" type="image/x-icon" href="$url_base/favicon.png">
23 48  
... ...
src/web/templates/package.html 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +$def with (pkg)
  2 +
  3 +<div class="graybox">
  4 +<table><tr><td class="noborder">
  5 +<h2>Details</h2>
  6 +<ul>
  7 + <li><b>Description</b>: $pkg['long_description']</li>
  8 + $if pkg['homepage']:
  9 + <li><b>Homepage</b>:<a href="$pkg['homepage']">$pkg['homepage']</a></li>
  10 + $if pkg['task']:
  11 + <li><b>Tasks</b>: $pkg['task']</li>
  12 + <li><b>Section</b>: $pkg['section']</li>
  13 + $if pkg['recommends']:
  14 + <li><b>Recommends</b>: $pkg['recommends']</li>
  15 + $if pkg['suggests']:
  16 + <li><b>Suggests</b>: $pkg['suggests']</li>
  17 + $if pkg['origin']:
  18 + <li><b>Origin</b>: $pkg['origin']</li>
  19 + <li><b>Maintainer</b>: $pkg['maintainer']</li>
  20 +</ul>
  21 +<h2>Debian resources:</h2>
  22 + <ul>
  23 + <li><a href="http://packages.debian.org/$pkg['package']">Package page on debian.org</a></li>
  24 + <li><a href="http://bugs.debian.org/$pkg['package']">Bug reports</a></li>
  25 + <li><a href="http://patch-tracker.debian.org/package/$pkg['package']">Debian patch tracking system</a></li>
  26 + <li><a href="http://packages.qa.debian.org/$pkg['package']">Debian package tracking system</a></li>
  27 + <li><a href="http://qa.debian.org/popcon.php?package=$pkg['package']">Popularity contest statistics</a></li>
  28 + </ul>
  29 +</td>
  30 +<td class="noborder">
  31 +<h2>Debtags</h2>
  32 +<ul>
  33 +$for facet, tags in pkg['tag'].items():
  34 + <li><b>$facet: </b></li>
  35 + <ul>
  36 + $for tag in tags:
  37 + <li>$tag</li>
  38 + </ul>
  39 +</ul>
  40 +</td>
  41 +
  42 +</tr></table>
  43 +</div>
  44 +
... ...