Commit 896fcc0700b027acebed531bcf18efa7ec2a1c02
1 parent
a7a750fa
Exists in
master
and in
1 other branch
Integrated recommender and new web form; changed section about; changes frontpage layout;
Showing
6 changed files
with
184 additions
and
124 deletions
Show diff stats
src/web/server.py
| @@ -6,6 +6,7 @@ import tempfile | @@ -6,6 +6,7 @@ import tempfile | ||
| 6 | import sys | 6 | import sys |
| 7 | import simplejson as json | 7 | import simplejson as json |
| 8 | import apt | 8 | import apt |
| 9 | +import re | ||
| 9 | 10 | ||
| 10 | sys.path.insert(0,"../") | 11 | sys.path.insert(0,"../") |
| 11 | 12 | ||
| @@ -15,44 +16,24 @@ from user import * | @@ -15,44 +16,24 @@ from user import * | ||
| 15 | 16 | ||
| 16 | import urllib | 17 | import urllib |
| 17 | 18 | ||
| 18 | -class RequestForm(form.Form): | ||
| 19 | - def __init__(self): | ||
| 20 | - form.Form.__init__(self, \ | ||
| 21 | - form.File("pkgs_file", size=35, description="Upload file"), | ||
| 22 | - form.Textarea("pkgs_list", description="Packages", | ||
| 23 | - rows="4", cols="52"), | ||
| 24 | - form.Dropdown('limit', [(5, '05'), (10, '10'), (20, '20')], | ||
| 25 | - description = "Limit"), | ||
| 26 | - form.Checkbox("strategy_cb", value=1, checked=False, | ||
| 27 | - description="Content-based"), | ||
| 28 | - form.Checkbox("strategy_col", value=1, checked=False, | ||
| 29 | - description="Collaborative"), | ||
| 30 | - form.Checkbox("strategy_hybrid", value="True", checked=False, | ||
| 31 | - description="Hybrid"), | ||
| 32 | - form.Checkbox("strategy_hybrid_plus", value="True", checked=False, | ||
| 33 | - description="Hybrid plus"), | ||
| 34 | - validators = [form.Validator("No packages list provided.", | ||
| 35 | - lambda f: f.has_key("pkgs_list") | | ||
| 36 | - f.has_key("pkgs_file") ), | ||
| 37 | - form.Validator("No strategy selected.", | ||
| 38 | - lambda f: f.has_key("strategy_cb") | | ||
| 39 | - f.has_key("startegy_col") | | ||
| 40 | - f.has_key("strategy_hybrid") | | ||
| 41 | - f.has_key("strategy_hybrid_plus")) ]) | ||
| 42 | - | ||
| 43 | class FeedbackForm(form.Form): | 19 | class FeedbackForm(form.Form): |
| 44 | - def __init__(self,strategies): | ||
| 45 | - desc_dict = {"cta": "Content-based", "col": "Collaborative", | ||
| 46 | - "hybrid": "Hybrib", "hybrid_plus": "Hybrid Plus"} | 20 | + def __init__(self,selected_strategies): |
| 21 | + desc_dict = {"cb": "Content-based", "cbt": "Content-based", | ||
| 22 | + "cbd": "Content-based", "col": "Collaborative", | ||
| 23 | + "hybrid": "Hybrib"} | ||
| 47 | fields = [] | 24 | fields = [] |
| 48 | - for strategy in strategies: | 25 | + for strategy in selected_strategies: |
| 49 | fields.append(form.Radio(desc_dict[strategy], | 26 | fields.append(form.Radio(desc_dict[strategy], |
| 50 | [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')])) | 27 | [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')])) |
| 51 | form.Form.__init__(self, *fields, validators = []) | 28 | form.Form.__init__(self, *fields, validators = []) |
| 52 | 29 | ||
| 53 | class Index: | 30 | class Index: |
| 54 | def GET(self): | 31 | def GET(self): |
| 55 | - return render.index("/apprec", "post", RequestForm()) | 32 | + return render.index() |
| 33 | + | ||
| 34 | +class About: | ||
| 35 | + def GET(self): | ||
| 36 | + return render.about() | ||
| 56 | 37 | ||
| 57 | class Thanks: | 38 | class Thanks: |
| 58 | def POST(self): | 39 | def POST(self): |
| @@ -95,52 +76,108 @@ class Package: | @@ -95,52 +76,108 @@ class Package: | ||
| 95 | subtags = [] | 76 | subtags = [] |
| 96 | return debtags | 77 | return debtags |
| 97 | 78 | ||
| 79 | +class Request: | ||
| 80 | + def __init__(self,web_input,user_id): | ||
| 81 | + self.user_id = user_id | ||
| 82 | + self.storage = web_input | ||
| 83 | + | ||
| 84 | + self.pkgs_list = [] | ||
| 85 | + if web_input.has_key('pkgs_list'): | ||
| 86 | + self.pkgs_list = web_input['pkgs_list'].encode('utf8').split() | ||
| 87 | + print self.pkgs_list | ||
| 88 | + print web_input['pkgs_file'] | ||
| 89 | + if web_input['pkgs_file']: | ||
| 90 | + f = open(outputdir + "/packages_list", "wb") | ||
| 91 | + lines = web_input['pkgs_file'].file.readlines() | ||
| 92 | + print lines | ||
| 93 | + if lines[0].startswith('POPULARITY-CONTEST'): | ||
| 94 | + del lines[0] | ||
| 95 | + del lines[-1] | ||
| 96 | + package_name_field = 2 | ||
| 97 | + else: | ||
| 98 | + package_name_field = 0 | ||
| 99 | + for line in lines: | ||
| 100 | + self.pkgs_list.append(line.split()[package_name_field]) | ||
| 101 | + f.write(line) | ||
| 102 | + f.close() | ||
| 103 | + | ||
| 104 | + if web_input.has_key('limit'): | ||
| 105 | + self.limit = int(web_input['limit']) | ||
| 106 | + if web_input.has_key('profile_size'): | ||
| 107 | + self.profile_size = int(web_input['profile_size']) | ||
| 108 | + if web_input.has_key('weight'): | ||
| 109 | + self.weight = web_input['weight'].encode('utf8') | ||
| 110 | + | ||
| 111 | + self.selected_strategies = [] | ||
| 112 | + if web_input.has_key('strategy'): | ||
| 113 | + if web_input['strategy'].encode('utf8') == "content": | ||
| 114 | + if (web_input.has_key('tag') and web_input.has_key('desc')): | ||
| 115 | + self.selected_strategies.append("cb") | ||
| 116 | + elif web_input.has_key('desc'): | ||
| 117 | + self.selected_strategies.append("cbd") | ||
| 118 | + else: | ||
| 119 | + self.selected_strategies.append("cbt") | ||
| 120 | + if web_input['strategy'].encode('utf8') == "collab": | ||
| 121 | + self.selected_strategies.append("col") | ||
| 122 | + if web_input['strategy'].encode('utf8') == "hybrid": | ||
| 123 | + self.selected_strategies.append("hybrid") | ||
| 124 | + | ||
| 125 | + if web_input.has_key('cluster'): | ||
| 126 | + self.cluster = bool(web_input.has_key['cluster'].encode('utf8')) | ||
| 127 | + | ||
| 128 | + if web_input.has_key('neighbours'): | ||
| 129 | + self.neighbours = int(web_input['neighbours']) | ||
| 130 | + | ||
| 131 | + self.profiles_set = set() | ||
| 132 | + if web_input.has_key('profile_desktop'): | ||
| 133 | + self.profiles = self.profiles.add("desktop") | ||
| 134 | + if web_input.has_key('profile_admin'): | ||
| 135 | + self.profiles = self.profiles.add("admin") | ||
| 136 | + if web_input.has_key('profile_devel'): | ||
| 137 | + self.profiles = self.profiles.add("devel") | ||
| 138 | + if web_input.has_key('profile_science'): | ||
| 139 | + self.profiles = self.profiles.add("science") | ||
| 140 | + if web_input.has_key('profile_arts'): | ||
| 141 | + self.profiles = self.profiles.add("arts") | ||
| 142 | + | ||
| 143 | + def __str__(self): | ||
| 144 | + return self.storage | ||
| 145 | + | ||
| 146 | + def validates(self): | ||
| 147 | + self.errors = [] | ||
| 148 | + if (not self.pkgs_list or not self.selected_strategies): | ||
| 149 | + self.errors.append("No upload file or packages list was provided.") | ||
| 150 | + return False | ||
| 151 | + if not self.selected_strategies: | ||
| 152 | + self.errors.append("No strategy was selected.") | ||
| 153 | + return False | ||
| 154 | + return True | ||
| 155 | + | ||
| 156 | + def get_strategy_details(self): | ||
| 157 | + return self.selected_strategies[0] | ||
| 98 | 158 | ||
| 99 | class AppRecommender: | 159 | class AppRecommender: |
| 100 | def POST(self): | 160 | def POST(self): |
| 161 | + print "post",web.input() | ||
| 101 | outputdir = tempfile.mkdtemp(prefix='',dir='./submissions/') | 162 | outputdir = tempfile.mkdtemp(prefix='',dir='./submissions/') |
| 102 | user_id = outputdir.lstrip('./submissions/') | 163 | user_id = outputdir.lstrip('./submissions/') |
| 103 | - request = RequestForm() | ||
| 104 | - request_info = web.input(pkgs_file={}) | ||
| 105 | - if not request.validates(request_info): | ||
| 106 | - return render.error(request) | 164 | + print web.input(pkgs_file={}) |
| 165 | + request = Request(web.input(pkgs_file={}),user_id) | ||
| 166 | + if not request.validates(): | ||
| 167 | + return render.error(request.errors) | ||
| 107 | else: | 168 | else: |
| 108 | - user_pkgs_list = [] | ||
| 109 | - if request_info.has_key('pkgs_list'): | ||
| 110 | - user_pkgs_list = request_info['pkgs_list'].encode('utf8').split() | ||
| 111 | - print user_pkgs_list | ||
| 112 | - | ||
| 113 | - if request_info['pkgs_file'].value: | ||
| 114 | - f = open(outputdir + "/packages_list", "wb") | ||
| 115 | - lines = request_info['pkgs_file'].file.readlines() | ||
| 116 | - print lines | ||
| 117 | - if lines[0].startswith('POPULARITY-CONTEST'): | ||
| 118 | - del lines[0] | ||
| 119 | - del lines[-1] | ||
| 120 | - package_name_field = 2 | ||
| 121 | - else: | ||
| 122 | - package_name_field = 0 | ||
| 123 | - for line in lines: | ||
| 124 | - user_pkgs_list.append(line.split()[package_name_field]) | ||
| 125 | - f.write(line) | ||
| 126 | - f.close() | ||
| 127 | - | ||
| 128 | - strategies = [] | ||
| 129 | - if request_info.has_key('strategy_cb'): strategies.append("cta") | ||
| 130 | - ### Colaborative strategies can not go online yet | ||
| 131 | - if request_info.has_key('strategy_col'): strategies.append("col") | ||
| 132 | - if request_info.has_key('strategy_hybrid'): | ||
| 133 | - strategies.append("hybrid") | ||
| 134 | - if request_info.has_key('strategy_hybrid_plus'): | ||
| 135 | - strategies.append("hybrid_plus") | ||
| 136 | - recommends = self._recommends(user_id,user_pkgs_list,strategies, int(request_info['limit'])) | 169 | + recommendation = self._recommends(request) |
| 137 | ### Getting package summary (short description) ### | 170 | ### Getting package summary (short description) ### |
| 138 | pkg_summaries = {} | 171 | pkg_summaries = {} |
| 139 | cache = apt.Cache() | 172 | cache = apt.Cache() |
| 140 | - for strategy, result in recommends.items(): | 173 | + for strategy, result in recommendation.items(): |
| 141 | for pkg in result: | 174 | for pkg in result: |
| 142 | - pkg_summaries[pkg] = cache[pkg].candidate.summary | ||
| 143 | - return render.apprec(recommends, pkg_summaries, FeedbackForm(strategies)) | 175 | + try: |
| 176 | + pkg_summaries[pkg] = cache[pkg].candidate.summary | ||
| 177 | + except: | ||
| 178 | + pkg_summaries[pkg] = "" | ||
| 179 | + return render.apprec(recommendation, pkg_summaries, | ||
| 180 | + FeedbackForm(request.selected_strategies),request) | ||
| 144 | 181 | ||
| 145 | # parsing json from screenshots - can be usefull in the future... | 182 | # parsing json from screenshots - can be usefull in the future... |
| 146 | # def _packages_attrs(self, recommends): #recommends is result of _recommends() | 183 | # def _packages_attrs(self, recommends): #recommends is result of _recommends() |
| @@ -156,18 +193,16 @@ class AppRecommender: | @@ -156,18 +193,16 @@ class AppRecommender: | ||
| 156 | # recommended_pkgs_attrs[pkg_attrs_dict['name']] = pkg_attrs_dict | 193 | # recommended_pkgs_attrs[pkg_attrs_dict['name']] = pkg_attrs_dict |
| 157 | # return recommended_pkgs_attrs | 194 | # return recommended_pkgs_attrs |
| 158 | 195 | ||
| 159 | - def _recommends(self,user_id,user_pkgs_list,strategies,limit): | ||
| 160 | - user = User(dict.fromkeys(user_pkgs_list,1),user_id) | 196 | + def _recommends(self,request): |
| 197 | + user = User(dict.fromkeys(request.pkgs_list,1),request.user_id) | ||
| 161 | user.maximal_pkg_profile() | 198 | user.maximal_pkg_profile() |
| 162 | cfg = Config() | 199 | cfg = Config() |
| 163 | rec = Recommender(cfg) | 200 | rec = Recommender(cfg) |
| 164 | results = dict() | 201 | results = dict() |
| 165 | - for strategy in strategies: | ||
| 166 | - ### Colaborative strategies can not go online yet | ||
| 167 | - #eval("rec."+strategy+"(cfg)") | ||
| 168 | - rec.cta(cfg) | ||
| 169 | - prediction = rec.get_recommendation(user).get_prediction(limit) | ||
| 170 | - results[rec.strategy.description] = \ | 202 | + for strategy_str in request.selected_strategies: |
| 203 | + rec.set_strategy(strategy_str) | ||
| 204 | + prediction = rec.get_recommendation(user).get_prediction(request.limit) | ||
| 205 | + results[strategy_str] = \ | ||
| 171 | [result[0] for result in prediction] | 206 | [result[0] for result in prediction] |
| 172 | return results | 207 | return results |
| 173 | 208 | ||
| @@ -181,9 +216,10 @@ def add_global_hook(): | @@ -181,9 +216,10 @@ def add_global_hook(): | ||
| 181 | render = web.template.render('templates/', base='layout') | 216 | render = web.template.render('templates/', base='layout') |
| 182 | render_plain = web.template.render('templates/') | 217 | render_plain = web.template.render('templates/') |
| 183 | 218 | ||
| 184 | -urls = ('/', 'Index', | ||
| 185 | - '/apprec', 'AppRecommender', | 219 | +urls = ('/', 'Index', |
| 220 | + '/apprec', 'AppRecommender', | ||
| 186 | '/thanks', 'Thanks', | 221 | '/thanks', 'Thanks', |
| 222 | + '/about', 'About', | ||
| 187 | '/package/(.*)', 'Package' | 223 | '/package/(.*)', 'Package' |
| 188 | ) | 224 | ) |
| 189 | 225 |
| @@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
| 1 | +$var title: About | ||
| 2 | +$var mod = 'about'; | ||
| 3 | + | ||
| 4 | +<div class="graybox"> | ||
| 5 | + <h1>What is this?</h1> | ||
| 6 | +<p>AppRecommender is a project in development that aims to provide solutions | ||
| 7 | +for application recommendation at the GNU/Linux world. It was initially thought | ||
| 8 | +as a Debian package recommender, but considering the multi-distro effort in | ||
| 9 | +providing platform independent solutions, it should also follow this | ||
| 10 | +principle.</p> | ||
| 11 | +</div> | ||
| 12 | + | ||
| 13 | +<div class="align-right"><img alt="AppRecommender logo" src="/static/images/AppRecommender-logo.jpg" width="320" /></div> | ||
| 14 | + |
src/web/templates/apprec.html
| 1 | -$def with (recommends, pkg_summaries, form) | 1 | +$def with (recommends, pkg_summaries, form, request) |
| 2 | $var title: Feedback | 2 | $var title: Feedback |
| 3 | $var mod = 'feedback'; | 3 | $var mod = 'feedback'; |
| 4 | 4 | ||
| 5 | - | ||
| 6 | <script type="application/x-javascript"> | 5 | <script type="application/x-javascript"> |
| 7 | $$(document).ready(function() { | 6 | $$(document).ready(function() { |
| 8 | inithandlers(); | 7 | inithandlers(); |
| @@ -12,18 +11,19 @@ $$(document).ready(function() { | @@ -12,18 +11,19 @@ $$(document).ready(function() { | ||
| 12 | </script> | 11 | </script> |
| 13 | 12 | ||
| 14 | <div class="graybox"> | 13 | <div class="graybox"> |
| 15 | - <h1>Results per strategy</h1> | ||
| 16 | -<ul class="toc"> | 14 | + <h1>Details of recommendation strategy</h1> |
| 15 | + $request.get_strategy_details() | ||
| 16 | +<!--<ul class="toc"> | ||
| 17 | $for strategy, result in recommends.items(): | 17 | $for strategy, result in recommends.items(): |
| 18 | <li><a href="#$strategy">$strategy</a></li> | 18 | <li><a href="#$strategy">$strategy</a></li> |
| 19 | </ul> | 19 | </ul> |
| 20 | -</div> | 20 | +</div>--> |
| 21 | 21 | ||
| 22 | -<form action="/thanks" method="post"> | 22 | +<form action="/thanks" method="post" enctype="multipart/form-data"> |
| 23 | <table> | 23 | <table> |
| 24 | <tbody> | 24 | <tbody> |
| 25 | $for strategy, result in recommends.items(): | 25 | $for strategy, result in recommends.items(): |
| 26 | - <h2><a name="$strategy" id="$strategy">$strategy</a></h2> | 26 | + <!--<h2><a name="$strategy" id="$strategy">$strategy</a></h2>--> |
| 27 | <tr> | 27 | <tr> |
| 28 | $ count = 0 | 28 | $ count = 0 |
| 29 | $for pkg in result: | 29 | $for pkg in result: |
src/web/templates/error.html
| 1 | -$def with (form) | 1 | +$def with (error_msgs) |
| 2 | $var title: Error | 2 | $var title: Error |
| 3 | $var mod = 'error'; | 3 | $var mod = 'error'; |
| 4 | 4 | ||
| @@ -11,10 +11,10 @@ $var mod = 'error'; | @@ -11,10 +11,10 @@ $var mod = 'error'; | ||
| 11 | 11 | ||
| 12 | Your request could not be proccessed due to the following error(s): | 12 | Your request could not be proccessed due to the following error(s): |
| 13 | 13 | ||
| 14 | -<ul> | ||
| 15 | -$for v in form.validators: | ||
| 16 | - <b><li>$v.msg</li></b> | ||
| 17 | -</ul> | 14 | +<p><ul> |
| 15 | +$for e in error_msgs: | ||
| 16 | + <b><li>$e</li></b> | ||
| 17 | +</ul></p> | ||
| 18 | 18 | ||
| 19 | <p><a href="/">Go back</a> and try again. </p> | 19 | <p><a href="/">Go back</a> and try again. </p> |
| 20 | <p>If you believe it is a bug, please report to <a | 20 | <p>If you believe it is a bug, please report to <a |
src/web/templates/index.html
| 1 | -$def with (action, method, form) | ||
| 2 | $var title: Home | 1 | $var title: Home |
| 3 | $var mod = 'index'; | 2 | $var mod = 'index'; |
| 4 | 3 | ||
| 5 | <div class="graybox"> | 4 | <div class="graybox"> |
| 6 | - <h1>What is this?</h1> | ||
| 7 | -<p>AppRecommender is a project in development that aims to provide solutions | ||
| 8 | -for application recommendation at the GNU/Linux world. It was initially thought | ||
| 9 | -as a Debian package recommender, but considering the multi-distro effort in | ||
| 10 | -providing platform independent solutions, it should also follow this | ||
| 11 | -principle.</p> | ||
| 12 | -</div> | 5 | +<h1>You might also like these packages...</h1> |
| 13 | 6 | ||
| 14 | -<div class="align-right"><img alt="AppRecommender logo" src="/static/images/AppRecommender-logo.jpg" width="320" /></div> | 7 | +<p>Provide a list of packages or upload a popcon submission file and you'll get |
| 8 | +a list of suggested packages automatically computed by AppRecommender. You can | ||
| 9 | +customize the recommender setup or let it randomly choose a setup for you.</p> | ||
| 15 | 10 | ||
| 11 | +<p>Please fill in the form that follows the recommendation results. Your | ||
| 12 | +feedback is very much appreciated!</p> | ||
| 16 | 13 | ||
| 14 | +<p>Enjoy it :)</p> | ||
| 15 | +</div> | ||
| 17 | 16 | ||
| 17 | +<!--<div class="align-right"><img alt="AppRecommender logo" | ||
| 18 | +src="/static/images/AppRecommender-logo.jpg" width="320" /></div>--> | ||
| 18 | 19 | ||
| 19 | -<form action="" name="weboptions"> | 20 | +<form action="apprec" enctype="multipart/form-data" method="post" name="weboptions"> |
| 20 | <p> | 21 | <p> |
| 22 | + <label>Upload file:<input type="file" id="pkgs_file" name="pkgs_file" size="35"/></label><br /> | ||
| 23 | + <label>Packages list:<textarea rows="2" cols="40" name="pkgs_list" id="pkgs_list"></textarea><label><br /> | ||
| 21 | <label>Profile size: <input type="text" name="profile_size" value="10"></label><br /> | 24 | <label>Profile size: <input type="text" name="profile_size" value="10"></label><br /> |
| 22 | - <label>Recommendations: <input type="text" name="recommendation_size" value="10"></label><br /> | ||
| 23 | - <label>Weighting scheme:<br /><input type="radio" name="scheme" value="BM25">BM25</label><br /> | ||
| 24 | - <label><input type="radio" name="scheme" value="trad"></label>Traditional<br /> | ||
| 25 | - <label>Strategy: <br /><input type="radio" name="strategy" value="content"> Content-based</label><br /> | ||
| 26 | - <label><input type="radio" name="strategy" value="collab"> Collaborative</label><br /> | ||
| 27 | - <label><input type="radio" name="strategy" value="hybrid"> Hybrid</label><br /> | 25 | + <label>Recommendation size: <input type="text" name="limit" value="10"></label><br /> |
| 26 | + <label>Weighting scheme:<br /> | ||
| 27 | + <input type="radio" name="weight" value="BM25" checked >BM25<br /> | ||
| 28 | + <input type="radio" name="weight" value="trad">Traditional<br /> | ||
| 29 | + </label> | ||
| 30 | + <label>Strategy: <br /> | ||
| 31 | + <input type="radio" name="strategy" value="content" checked> Content-based<br /> | ||
| 32 | + <input type="radio" name="strategy" value="collab"> Collaborative<br /> | ||
| 33 | + <input type="radio" name="strategy" value="hybrid"> Hybrid<br /> | ||
| 34 | + </label> | ||
| 28 | <!-- <label>Password:<input type="password" name="pass"></label> --> | 35 | <!-- <label>Password:<input type="password" name="pass"></label> --> |
| 29 | - <label style="margin-bottom: 1em; padding-bottom: 1em; border-bottom: 3px silver groove;"><input type="hidden" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"></label> | ||
| 30 | - <label><input type="checkbox" name="ssh" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"> Tag</label> | ||
| 31 | - <label><input type="checkbox" name="iis" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"> Description</label> | ||
| 32 | - <br /><label><input type="checkbox" name="asp" class="DEPENDS ON strategy BEING collab OR strategy BEING hybrid"> Clustering</label><br /> | ||
| 33 | - <label>Neighbours: <input type="text" name="neighbours" class="DEPENDS ON strategy BEING collab OR strategy BEING hybrid" value="50"></label><br /> | ||
| 34 | - | ||
| 35 | - <label>Personal profile: <br /><input type="checkbox" name="user_desktop" checked class="DEPENDS ON strategy BEING hybrid">Desktop</label> | ||
| 36 | - <label><input type="checkbox" name="neighbours" class="DEPENDS ON strategy BEING hybrid">Admin</label> | ||
| 37 | - <label><input type="checkbox" name="neighbours" class="DEPENDS ON strategy BEING hybrid">Devel</label> | ||
| 38 | - <label><input type="checkbox" name="neighbours" class="DEPENDS ON strategy BEING hybrid">Science</label> | ||
| 39 | - <label><input type="checkbox" name="neighbours" class="DEPENDS ON strategy BEING hybrid">Arts</label> | 36 | + <!-- <label style="margin-bottom: 1em; padding-bottom: 1em; border-bottom: 3px silver groove;"><input type="hidden" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"></label> --> |
| 37 | + </p><p> | ||
| 38 | + <label>Content attributes: | ||
| 39 | + <input type="radio" name="content" value="tag" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid" checked> tag | ||
| 40 | + <input type="radio" name="content" value="desc" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"> description | ||
| 41 | + <input type="radio" name="content" value="full" class="DEPENDS ON strategy BEING content OR strategy BEING hybrid"> both | ||
| 42 | + </label><br /> | ||
| 43 | + <label>Clustering | ||
| 44 | + <input type="radio" name="cluster" value="True" class="DEPENDS ON strategy BEING collab OR strategy BEING hybrid" checked> Yes | ||
| 45 | + <input type="radio" name="cluster" value="False" class="DEPENDS ON strategy BEING collab OR strategy BEING hybrid"> No | ||
| 46 | + </label><br /> | ||
| 47 | + <label>Neighbours: | ||
| 48 | + <input type="text" name="neighbours" class="DEPENDS ON strategy BEING collab OR strategy BEING hybrid" value="50"> | ||
| 49 | + </label><br /> | ||
| 50 | + <label>Personal profile: | ||
| 51 | + <input type="checkbox" name="profile_desktop" class="DEPENDS ON strategy BEING hybrid" checked>Desktop | ||
| 52 | + <input type="checkbox" name="profile_admin" class="DEPENDS ON strategy BEING hybrid">Admin | ||
| 53 | + <input type="checkbox" name="profile_devel" class="DEPENDS ON strategy BEING hybrid">Devel | ||
| 54 | + <input type="checkbox" name="profile_science" class="DEPENDS ON strategy BEING hybrid">Science | ||
| 55 | + <input type="checkbox" name="profile_arts" class="DEPENDS ON strategy BEING hybrid">Arts | ||
| 56 | + </label> | ||
| 40 | </p> | 57 | </p> |
| 41 | <input type="submit" /> | 58 | <input type="submit" /> |
| 42 | </form> | 59 | </form> |
| 43 | 60 | ||
| 44 | -<!-- | ||
| 45 | -<form action="$action" enctype="multipart/form-data" method="$method"> | ||
| 46 | -$:form.render() | ||
| 47 | -<br /> | ||
| 48 | -<input type="submit" /> | ||
| 49 | -</form> | ||
| 50 | ---> |
src/web/templates/layout.html
| 1 | $def with (content) | 1 | $def with (content) |
| 2 | -$ url_base = "http://localhost:8080/" | 2 | +$ url_base = "http://localhost:8080" |
| 3 | 3 | ||
| 4 | <!DOCTYPE html> | 4 | <!DOCTYPE html> |
| 5 | <html lang="en"><head> | 5 | <html lang="en"><head> |
| @@ -133,7 +133,7 @@ function hideMesg(){ | @@ -133,7 +133,7 @@ function hideMesg(){ | ||
| 133 | <div id="nav"> | 133 | <div id="nav"> |
| 134 | <a href="$url_base">Home</a> | 134 | <a href="$url_base">Home</a> |
| 135 | | | 135 | | |
| 136 | - <a href="http://www.ime.usp.br/~tassia/apprec.html">About</a> | 136 | + <a href="$url_base/about">About</a> |
| 137 | | | 137 | | |
| 138 | <a href="http://github.com/tassia/AppRecommender">Devel</a> | 138 | <a href="http://github.com/tassia/AppRecommender">Devel</a> |
| 139 | </div> | 139 | </div> |