Web · Wiki · Activities · Blog · Lists · Chat · Meeting · Bugs · Git · Translate · Archive · People · Donate

Commit 1526404f977757226da395eb5525758ee091ff3d

Initial implementation of artifacts upload.
app/app.py
(130 / 18)
  
1616
1717import logging
1818import sys
19import os
1920import locale
2021from math import ceil
2122from string import join, split
2727 redirect, session, render_template, render_template_string, g
2828from flaskext.babel import Babel, gettext as _, format_datetime
2929from werkzeug import Headers
30from werkzeug import secure_filename
31
3032import simplejson
33import tempfile
3134
3235from sugar_network import sugar
3336from client import Client
3437
3538_BUFFER_SIZE = 1024 * 10
39UPLOAD_FOLDER = tempfile.mkdtemp()
40WWW = None # regular browser or embedded
3641
3742""" Initialization of local app """
3843app = Flask(__name__)
4545babel = Babel(app)
4646app.config['BABEL_DEFAULT_LOCALE'] = 'en'
4747app.config['BABEL_DEFAULT_TIMEZONE'] = 'America/Lima'
48app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
4849
4950from cursors import *
5051mounts = network_mount.client.mounts()
5353
5454@babel.localeselector
5555def get_locale():
56 global WWW
5657 # try to guess the language from the user accept
5758 # header the browser transmits.
5859 lang = request.accept_languages.best_match(['es', 'en'])
6161 # otherwise we're probably embedded, get from env
6262 lang = locale.getdefaultlocale()[0].split('_')[0]
6363 logging.debug('Locale from env: %s' % lang)
64 WWW = False
6465 else:
6566 logging.debug('Locale from headers: %s' % lang)
67 WWW = True
6668 return lang
6769
6870
127127 g.client = home_mount.client
128128 g.Contexts = home_mount.Contexts
129129 g.Activities = home_mount.Activities
130 g.Artifacts = home_mount.Artifacts
130131 g.Projects = home_mount.Projects
131132 g.autocomplete_Contexts = home_mount.autocomplete_Contexts
132133 g.Questions = home_mount.Questions
141141 g.client = network_mount.client
142142 g.Contexts = network_mount.Contexts
143143 g.Activities = network_mount.Activities
144 g.Artifacts = network_mount.Artifacts
144145 g.Projects = network_mount.Projects
145146 g.autocomplete_Contexts = network_mount.autocomplete_Contexts
146147 g.Questions = network_mount.Questions
227227 return Response(download(context), headers=header, direct_passthrough=True)
228228
229229
230@app.route('/artifacts/preview/<guid>')
231def gen_preview(guid):
232 artifact = g.client.Artifact(guid)
233
234 def download(artifact):
235 with artifact.get_blob('preview') as icon:
236 if icon.closed:
237 icon = app.open_resource('static/icons/document-generic.png')
238 while True:
239 chunk = icon.read(_BUFFER_SIZE)
240 if not chunk:
241 break
242 yield chunk
243
244 header = Headers()
245 header.add("Content-Type", "image/png")
246 return Response(download(artifact), headers=header,
247 direct_passthrough=True)
248
249
230250@app.route('/launch/<context_guid>')
231251def launch(context_guid):
232252 g.client.launch(context_guid)
270270 return render_template('resource-form.html', context=context)
271271
272272
273@app.route('/artifacts/upload/to_context/<context>')
274@app.route('/artifacts/upload')
275def artifact_upload(context=''):
276 return render_template('upload-form.html',
277 context=context)
278
279
280@app.route('/artifacts/upload', methods=['POST'])
281def artifact_post():
282 artifact = g.client.Artifact()
283 artifact['context'] = request.form['context']
284 artifact['description'] = request.form['content']
285
286 upload = request.files['artifact_file']
287 if upload:
288 filename = secure_filename(upload.filename)
289 artifact['title'] = filename
290 full_filename = os.path.join(app.config['UPLOAD_FOLDER'], filename)
291 upload.save(full_filename)
292 artifact.post()
293
294 if filename:
295 artifact.upload_blob('data', full_filename)
296
297 return redirect('/context/artifacts/' + request.form['context'])
298
299
300@app.route('/artifacts/copy/<guid>')
301def artifact_copy(guid):
302 artifact = g.client.Artifact(guid, reply=['guid', 'title', 'context'])
303 filename = artifact['title']
304 blob = artifact.get_blob('data')
305 from shutil import copy
306 copy(blob.name, '/tmp/' + filename)
307 return redirect('/context/artifacts/' + artifact['context'])
308
309
310@app.route('/artifacts/download/<guid>')
311def artifact_download(guid):
312 if not WWW:
313 return redirect(url_for('artifact_copy', guid=guid))
314
315 artifact = g.client.Artifact(guid, reply=['guid', 'title'])
316 filename = artifact['title']
317
318 def download(artifact):
319 with artifact.get_blob('data') as data:
320 while True:
321 chunk = data.read(_BUFFER_SIZE)
322 if not chunk:
323 break
324 yield chunk
325
326 header = Headers()
327 header.add("Content-Type", "application/octet-stream")
328 header.add("Content-Disposition", "attachment; filename=" + filename)
329
330 return Response(download(artifact), headers=header,
331 direct_passthrough=True)
332
333
273334@app.route('/_report')
274335def report():
275336 return render_template('report-form.html',
452452 return r, total_pages, result.total, info
453453
454454
455@app.route('/resource/artifacts')
455456@app.route('/resource/search/')
456457@app.route('/resource/search/<query>')
457458@app.route('/resource/reviews')
494494 elif resource == 'reviews':
495495 resource_object = g.Reviews
496496 resource_label = _("reviews")
497 elif resource == 'artifacts':
498 resource_object = g.Artifacts
499 resource_label = _("artifacts")
497500 elif resource == 'all':
498501 resource_object = g.Resources
499502 resource_label = _("resources")
517517 total=total, resource_label=resource_label)
518518
519519 if '_pjax' in request.args:
520 template = '_resource-list.html'
520 if resource == 'artifacts':
521 template = '_artifact-list.html'
522 else:
523 template = '_resource-list.html'
521524 else:
522525 template = 'resource-list.html'
523526 kwargs = {str(resource): 'button_selected'}
527 if resource == 'artifacts':
528 kwargs['inner_template'] = '_artifact-list.html'
529 kwargs['artifacts_view'] = 'true'
530 else:
531 kwargs['resource_view'] = 'true'
524532 return render_template(template, query=query, resource=resource,
525533 result=r, type='resource', page=page, info=info,
526 total_pages=total_pages, meta=meta, resource_view='true',
534 total_pages=total_pages, meta=meta,
527535 resource_type=resource_type, **kwargs)
528536
529537
682682
683683@app.route('/context/reviews/<resource_guid>')
684684@app.route('/context/wikiwiki/<resource_guid>')
685@app.route('/context/gallery/<resource_guid>')
685#@app.route('/context/gallery/<resource_guid>')
686686@app.route('/review/<review_guid>')
687687def reviews_browser(resource_guid=None, review_guid=None):
688688 if review_guid:
757757@app.route('/context/questions/<context_guid>')
758758@app.route('/context/ideas/<context_guid>')
759759@app.route('/context/problems/<context_guid>')
760@app.route('/context/artifacts/<context_guid>')
761@app.route('/context/gallery/<context_guid>')
760762@app.route('/context/all/<context_guid>')
761763def context_resource_browser(context_guid=None, query=None):
762764 """
770770 else:
771771 return redirect(request.path + "?page=1")
772772
773 resource_type = split(request.path, "/")[2][:-1]
774 if resource_type == 'question':
773 resource_type = split(request.path, "/")[2]
774 if resource_type == 'questions':
775775 resource_object = g.Questions
776776 resource_label = _("questions")
777 elif resource_type == 'problem':
777 elif resource_type == 'problems':
778778 resource_object = g.Problems
779779 resource_label = _("problems")
780 elif resource_type == 'idea':
780 elif resource_type == 'ideas':
781781 resource_object = g.Ideas
782782 resource_label = _("ideas")
783 elif resource_type == 'al':
783 elif resource_type == 'artifacts' or resource_type == 'gallery':
784 resource_type = 'artifacts'
785 resource_object = g.Artifacts
786 resource_label = _("artifacts")
787 elif resource_type == 'all':
784788 resource_object = g.Resources
785789 resource_label = _("resources")
786 resource_type = 'all'
787790
788791 try:
789792 r, total_pages, total, info = paginate(resource_object,
813813
814814 stroke, fill = get_colors()
815815 if '_pjax' in request.args:
816 template = '_context-resource-list.html'
816 if resource_type == 'artifacts':
817 template = '_context-artifact-list.html'
818 else:
819 template = '_context-resource-list.html'
817820 _pjax = True
818821 else:
819822 template = 'context-view.html'
820823 _pjax = False
821824
822 if resource_type == 'all':
823 kwargs = {str(resource_type): 'button_selected'}
824 else:
825 #add the plural form
826 kwargs = {str(resource_type) + 's': 'button_selected'}
827 return render_template(template, result=r,
825 kwargs = {str(resource_type): 'button_selected'}
826 if resource_type == 'artifacts':
827 kwargs['inner_template'] = '_context-artifact-list.html'
828
829 return render_template(template, result=r, resource_type=resource_type,
828830 total_pages=total_pages, info=info, meta=meta,
829831 resource_label=resource_label, stroke=stroke,
830 resource_type=resource_type, context=context,
831 page=page, fill=fill, _pjax=_pjax, **kwargs)
832 context=context, page=page, fill=fill,
833 _pjax=_pjax, **kwargs)
832834
833835
834836@app.route('/submit_edit', methods=['POST'])
  
8181 reply=['guid', 'type', 'title', 'content', 'context', 'author',
8282 'user', 'tags', 'mtime'], order_by='-mtime')
8383 self.Artifacts = self.client.Artifact.cursor(
84 reply=['guid', 'title', 'content', 'context', 'author',
85 'user', 'tags', 'mtime'], order_by='-mtime')
84 reply=['guid', 'title', 'description', 'context', 'filesize',
85 'user', 'author', 'tags', 'mtime', 'traits', 'preview'],
86 order_by='-mtime')
8687
8788
8889network_mount = Mount('/')
  
6666 top: 0;
6767 margin: 0px 0px 0px 0px;
6868 height: 55px;
69 width: 100%;
69 width: 100%;
7070 background-color: #1f210c;
7171 color: white;
7272 vertical-align: middle;
8181 line-height: 2em;
8282 padding: 9px 10px;
8383 padding-left: 55px;
84 border-radius: 15px;
84 border-radius: 15px;
8585 -moz-border-radius: 15px;
8686 -webkit-border-radius: 15px;
8787 background-image: url(/static/images/tuki.png);
172172 -webkit-border-radius: 15px;
173173 }
174174
175img.inline_images {
176 vertical-align:middle;
177 }
175178
179img.small_preview {
180 width: 55px;
181 height: 55px;
182 }
183
176184#tags-section {
177185}
178186
336336
337337div.comments {
338338 width: 400px;
339 display:none;
339 display:none;
340340 }
341341div.comment-content {
342342 color: #808080;
415415div.resource-meta {
416416 color: #9ccec9;
417417 position: absolute;
418 bottom: 1px;
418 bottom: 1px;
419419 right: 30px;
420420 }
421421.mtime {
487487/*** grid view styles ***/
488488
489489div.context-grid-box {
490 width: 900px;
490 width: 900px;
491491 height: 550px;
492492 }
493493
507507div.context-info {
508508 position: fixed;
509509 }
510
510
511511div.iconbox {
512512 height: 120px;
513513 width: 150px;
553553
554554.iconbox a {
555555 color: black;
556 text-decoration: none;
556 text-decoration: none;
557557 }
558558
559559.grid-icon {
574574 border-radius: 15px;
575575 -moz-border-radius: 15px;
576576 -webkit-border-radius: 15px;
577 z-index: 50;
577 z-index: 50;
578578 }*/
579579
580580.question-icon {
582582 left:15px;
583583 position:absolute;
584584 background-color: #fff;
585 z-index: 60;
585 z-index: 60;
586586 }
587587.review-icon {
588588 top:25px;
589 left:195px;
589 left:195px;
590590 position:absolute;
591591 background-color: #fff;
592 z-index: 60;
592 z-index: 60;
593593 }
594594.idea-icon {
595595 top:65px;
596596 left:15px;
597597 position:absolute;
598598 background-color: #fff;
599 z-index: 60;
599 z-index: 60;
600600 }
601601.gallery-icon {
602 top:65px;
602 top:105px;
603603 left:195px;
604604 position:absolute;
605605 background-color: #fff;
606 z-index: 60;
606 z-index: 60;
607607 }
608608.problem-icon {
609609 top:105px;
610610 left:15px;
611611 position:absolute;
612612 background-color: #fff;
613 z-index: 60;
613 z-index: 60;
614614 }
615615.wiki-icon {
616 top:105px;
616 top:65px;
617617 left:195px;
618618 position:absolute;
619619 background-color: #fff;
620 z-index: 60;
620 z-index: 60;
621621 }
622622
623623
679679 }
680680#mejorar-sistema-form {
681681 position: fixed;
682 bottom: 80px;
682 bottom: 80px;
683683 right: 20px;
684/* left: 49%;
684/* left: 49%;
685685 top: 40%; */
686686 width: 580px;
687687 height: 300px;
714714#accordion {
715715 top: 330px;
716716 position:fixed;
717 border-radius: 15px;
717 border-radius: 15px;
718718 -moz-border-radius: 15px;
719719 -webkit-border-radius: 15px;
720720 padding:15px;
728728/* accordion header */
729729#accordion h2 {
730730 text-indent: 16px;
731 background:#98c40c;
731 background:#98c40c;
732732 line-height: 14px;
733733 margin:0;
734734 padding:5px 15px;
752752#accordion .pane {
753753 border:1px solid #fff;
754754 border-width:0 2px;
755 display:none;
755 display:none;
756756 height:180px;
757757 padding:15px;
758758 color:black;
780780
781781div.browser-iconbox {
782782 height: 80px;
783 width: 100%;
783 width: 100%;
784784 }
785785
786786div.browser-title {
880880 }
881881
882882.window-buttons {
883 float: right;
883 float: right;
884884 }
885885img.window-button {
886886 width: 40px;
902902 }
903903
904904textarea.resource-inputarea {
905 width: 75%;
905 width: 75%;
906906 /*position: absolute;
907907 top: 150px;*/
908908 bottom: 20px;
943943 }
944944
945945#resource-buttons {
946 padding: 20px;
946 padding: 20px;
947947 padding-bottom: 10px;
948948 margin-left:120px;
949949 text-align: left;
950950 }
951951
952952#resource-buttons img {
953 clear:both;
953 clear:both;
954954 margin-left: 40px;
955955 }
956956
957957#submit-buttons img {
958 clear:both;
958 clear:both;
959959 margin-left: 50px;
960960 }
961961
10671067 height: 500px;
10681068 margin-left: 55px;
10691069}
1070
1070
10711071/*
10721072root element for scrollable items. Must be absolutely positioned
10731073and it should have a extremely large width to accommodate scrollable
10901090 width:900px;
10911091 position:absolute;
10921092}
1093
1093
10941094/*
10951095a single item. must be floated in horizontal scrolling. typically,
10961096this element is the one that *you* will style the most.
11021102/* prev, next, prevPage and nextPage buttons */
11031103a.browse {
11041104 background:url(/static/images/hori_large.png) no-repeat;
1105 display:block;
1105 display:block;
11061106 width:30px;
11071107 height:30px;
1108 float:left;
1108 float:left;
11091109 margin:4px 0 0 0;
11101110 cursor:pointer;
11111111 font-size:1px;
11791179 position:absolute;
11801180 display:block;
11811181 margin-top:1px;
1182 border:1px solid #98C40C;
1182 border:1px solid #98C40C;
11831183 cursor:pointer;
11841184 border-radius:5px;
11851185 -moz-border-radius:5px;
12561256 height: 90px;
12571257 }
12581258 #resource-list-scrollable {
1259 height: 600px;
1259 height: 600px;
12601260 }
12611261 ul.resource-list {
12621262 height: 600px;
13331333 }
13341334 #scrollable {
13351335 left: 30px;
1336 width: 750px;
1336 width: 750px;
13371337 }
13381338 .slider {
13391339 width: 450px;
13401340 }
13411341 div.context-grid-box {
1342 width: 750px;
1342 width: 750px;
13431343 }
13441344 .idea-icon {
13451345 left:5px;
  
1 <ul class="resource-list" id="resource-page-{{page}}">
2 {%- for item in result %}
3 <li class="resource-list">
4 <div class="icon-column">
5 <a href="/context/artifacts/{{item['context']}}">
6 <img class="has_tooltip" src="/context/icon/{{item['context']}}" title="{{_('context resources')}}" />
7 </a>
8 </div>
9 <div class="icon-column">
10 {%- if item['author'] %}
11 <img src="/static/icons/sugar-xo.png"/>
12 {%- endif %}
13 </div>
14 <div class="icon-column res_type_col">
15 <a href="/artifacts/download/{{item['guid']}}">
16 <img class="has_tooltip small_preview" src="/artifacts/preview/{{item['guid']}}" title="{{_('download artifact')}}"/>
17 </a>
18 </div>
19 <div class="summary-column">
20 {%- if resource_type!='review' %}
21 <div class="resource-title">
22 <a class="has_tooltip" title="{{_('see more')}}" href="/artifacts/download/{{item['guid']}}">
23 {{item['title']}}</a>
24 </div>
25 {%- endif %}
26 <div class="resource-content-row">
27 <a class="has_tooltip" title="{{_('see more')}}" href="/artifacts/download/{{item['guid']}}">
28 {{item['description']}}</a>
29 </div>
30 <div class="resource-meta">
31 {{_('by %(author)s on %(date)s', author=item['author'][0], date=item['mtime']|timedelta)}}
32 {%- for tag in item['tags'] %}
33 <span class="tag">{{tag}}</span>
34 {%- endfor %}
35 </div>
36 </div>
37 <!--
38 <div class="icon-column">
39 %- if item['keep'] %
40 <img class="star" src="/static/icons/emblem-favorite.png"/>
41 %- else %
42 <img class="star" src="/static/icons/add-link.png"/>
43 %- endif %
44 </div>
45 -->
46 {%- if resource_type!='review' %}
47 <div class="meta-column">
48 <div>
49 {{_('followers')}}
50 </div>
51 <div>
52 {{_('comments')}}
53 </div>
54 <div>
55 {{_('solutions')}}
56 </div>
57 </div>
58 {%- endif %}
59 </li>
60
61 {%- endfor %}
62 </ul>
  
1313 <a href="/context/reviews/{{context['guid']}}">
1414 <img class="box-button review-icon has_tooltip" src="/static/icons/button-review.png" title="{{_('reviews')}}"/>
1515 </a>
16 <a href="/context/gallery/{{context['guid']}}">
17 <img class="box-button gallery-icon has_tooltip" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
18 </a>
1916 <a href="/context/all/{{context['guid']}}">
2017 <img class="box-button wiki-icon has_tooltip" src="/static/icons/button-list.png" title="{{_('all resources')}}" />
2118 </a>
19 <a href="/context/gallery/{{context['guid']}}">
20 <img class="box-button gallery-icon has_tooltip" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
21 </a>
2222
23 {%- if 'activity' in context['type'] -%}
23 {%- if 'activity' in context['type'] -%}
2424 <div class="iconbox has_tooltip" title="{{_('launch') + ' ' + context['title']}}">
2525 <a href="/launch/{{context['guid']}}">
2626 {%- else -%}
3030 <img class="grid-icon" src="/context/icon/{{context['guid']}}?cursor_offset={{context.offset}}" />
3131 </a>
3232 </div>
33 <div class="context-label">
33 <div class="context-label">
3434 <span class="context-controls">
35 <img title="{{_('available offline')}}" id="moon-{{context['guid']}}"
35 <img title="{{_('available offline')}}" id="moon-{{context['guid']}}"
3636 {% if context['keep_impl'] %}
3737 style="background-color:{{fill}}; border: 1px solid {{stroke}};"
3838 data-keep_impl="true"
39 {% endif %}
39 {% endif %}
4040 class="moon-emblem has_tooltip" src="/static/icons/moon.png"/>
41
42 <img title="{{_('favorite')}}" id="star-{{context['guid']}}"
41
42 <img title="{{_('favorite')}}" id="star-{{context['guid']}}"
4343 {% if context['keep'] %}
4444 style="background-color:{{fill}}; border: 1px solid {{stroke}};"
4545 data-keep="true"
46 {% endif %}
46 {% endif %}
4747 class="star-emblem has_tooltip" src="/static/icons/add-link-small.png"/>
4848 </span>
4949 &nbsp;
  
1 {%- if not _pjax %}
2 <div class="resource-scrollable" id="resource-scrollable">
3 <div class="items">
4 {%- for item in range(page-1) %}
5 <ul class='browser-page' id="resource-page-{{item+1}}">
6 <div id='throbber-box'>
7 <img id='throbber' src="/static/images/throbber10.gif" />
8 </div>
9 </ul>
10 {%- endfor %}
11 <ul class="browser-page" id='resource-page-{{page}}'>
12 {%- endif %}
13 {%- for item in result %}
14 <li class="resource-list">
15 <div class="icon-column res_type_col">
16 <a href="/artifacts/download/{{item['guid']}}">
17 <img class="small_preview" src="/artifacts/preview/{{item['guid']}}"/>
18 </a>
19 </div>
20 <div class="icon-column">
21 {%- if item['author'] %}
22 <img src="/static/icons/sugar-xo.png"/>
23 {%- endif %}
24 </div>
25 <div class="summary-column-context">
26 <div class="resource-title">
27 <a href="/artifacts/download/{{item['guid']}}"
28 class="artifact-link"
29 data-href="/artifacts/download/{{item['guid']}}">
30 {{item['title']|safe}}</a>
31 </div>
32 <div class="resource-content-row">
33 <a href="/artifacts/download/{{item['guid']}}"
34 data-href="/artifacts/download/{{item['guid']}}">
35 {{item['description']|safe}}
36 </a>
37 </div>
38 <div class="mtime">
39 {{_('by %(author)s on %(date)s', author=item['author'][0], date=item['mtime']|timedelta)}}
40 </div>
41 <div class="resource-meta">
42 {%- for tag in item['tags'] %}
43 <span class="tag">{{tag}}</span>
44 {%- endfor %}
45 </div>
46 <!--div class="meta-column">
47 <div>
48 {{_('followers')}}
49 </div>
50 <div>
51 {{_('comments')}}
52 </div>
53 <div>
54 {{_('solutions')}}
55 </div>
56 </div-->
57 </div>
58 </li>
59 {%- endfor %}
60 {%- if not result %}
61 <div id="notice-window">
62 <div class="notice">{{_('No %(resource)s have been shared yet for this context.<br><br>Be the first to contribute with the community!', resource=resource_label )}}
63 </div>
64 </div>
65 {%- endif %}
66 {%- if not _pjax %}
67 </ul>
68 {%- for item in range(total_pages-page) %}
69 <ul class='browser-page' id="resource-page-{{item+page+1}}">
70 <div id='throbber-box'>
71 <img id='throbber' src="/static/images/throbber10.gif" />
72 </div>
73 </ul>
74 {%- endfor %}
75 </div>
76 </div>
77 <div id="mejorar-sistema">
78 <!--img onclick="location='/new/resource?cursor_offset={{context_offset}}'" class="toolbar-icon white-button" src="/static/icons/list-add.png" /-->
79 <img onclick="location.href='/artifacts/upload/to_context/{{context['guid']}}'" class="toolbar-icon white-button" src="/static/icons/list-add.png" />
80 </div>
81 {%- if result %}
82 <div id='vpaginator'>
83 <input id="vrange" type="range" name="vpaginator" max="1" min="{{total_pages}}" step="-1" value="{{page}}" />
84 </div>
85 <style>
86 .slider {
87 height:280px;
88 width:6px;
89 position: fixed;
90 right: 20px;
91 top: 150px;
92 }
93 .handle {
94 left:-10px;
95 }
96 </style>
97 {%- endif %}
98 {%- endif %}
  
33 <meta charset="UTF-8" />
44 <title>{{_('Welcome to Sugar Network')}}</title>
55 <link rel="shortcut icon" href="{{ url_for('static', filename='icons/favicon.ico') }}">
6 <link rel="stylesheet" href="/static/css/browser.css" type="text/css" />
6 <link rel="stylesheet" href="/static/css/browser.css" type="text/css" />
77 <link rel="stylesheet" href="/static/css/sugar-theme/jquery-ui-1.8.16.sugar.css" />
88 <script src="/static/js/jquery.tools.min.js"></script>
99 <script src="/static/js/jquery.history.js"></script>
1010 <script src="/static/js/jquery-ui-1.8.16.sugar.min.js" type="text/javascript"></script>
1111 <script src="/static/js/jquery.livequery.min.js" type="text/javascript" charset="utf-8"></script>
1212 <style>
13 .sugar-network-online {
13 .sugar-network-online {
1414 background-color: {{fill}};
1515 border: 4px solid {{stroke}};
1616 border-radius: 15px;
1818 -webkit-border-radius: 15px;
1919 padding: 2px;
2020 }
21 .ui-autocomplete-loading {
22 background: white url('/static/images/throbber5.gif') right center no-repeat;
21 .ui-autocomplete-loading {
22 background: white url('/static/images/throbber5.gif') right center no-repeat;
2323 }
2424 .grid-icon:hover {
2525 color: white;
2929 border-radius: 15px;
3030 -moz-border-radius: 15px;
3131 -webkit-border-radius: 15px;
32 z-index: 50;
32 z-index: 50;
3333 }
3434 @media (max-width:801px) {
3535 body {}
7878 {%- if (session['connected'] or False) -%}
7979 <form id="resource-form1" method="POST" action="/submit_resource">
8080 <div class="resource-form-field">
81 <span id="title_label">{{_('Title')}}</span><br/>
81 <span id="title_label">{{_('Title')}}</span><br/>
8282 <input name="guid" type="hidden" value="{{session['last_context']}}" />
8383 <input onkeypress="return event.keyCode != 13;" name="title" id="title" class="resource-input" type="text"/>
8484 <input id="resource_type" name="resource_type" type="hidden" value="" />
8686 <input id="edit_guid" name="edit_guid" type="hidden" value="" />
8787 </div>
8888 <div class="resource-form-field" id="summary_section">
89 <span id="summary_label">{{_('Summary')}}</span><br/>
89 <span id="summary_label">{{_('Summary')}}</span><br/>
9090 <input onkeypress="return event.keyCode != 13;" id="summary" name="summary" class="resource-input" type="text"/>
9191 </div>
9292 <div class="resource-form-field">
116116 var oldh;
117117 var oldw;
118118
119 (function(window,undefined){
119 (function(window,undefined){
120120 // Prepare History.js
121121 var History = window.History; // Note: We are using a capital H instead of a lower h
122122 if ( !History.enabled ) {
142142 $('#details_label').empty().append('{{_("Article")}}');
143143 $('textarea.resource-inputarea').css('height', '170px');
144144 dialog.expose({
145 closeOnClick: false,
145 closeOnClick: false,
146146 onBeforeClose: function(event) {
147147 dialog.fadeOut(
148148 function () {
158158 $('textarea#edit-content').val('');
159159 }
160160 );
161 }
161 }
162162 });
163163 dialog.fadeIn();
164164 $('input#title').val(title);
183183 $("#resource-form1").submit();
184184 $('#mejorar-sistema-form').fadeOut();
185185 });
186
186
187187 $('#cancel-button').click( function () {
188188 $('#mejorar-sistema-form').fadeOut();
189189 $.mask.close();
203203 $('#details_label').empty().append('{{_("Article")}}');
204204 $('textarea.resource-inputarea').css('height', '170px');
205205 dialog.expose({
206 closeOnClick: false,
206 closeOnClick: false,
207207 onBeforeClose: function(event) {
208208 dialog.fadeOut(
209209 function () {
219219 $('textarea#edit-content').val('');
220220 }
221221 );
222 }
222 }
223223 });
224224 dialog.fadeIn();
225225 $('input#title').val(title);
245245 $("#resource-form1").submit();
246246 $('#mejorar-sistema-form').fadeOut();
247247 });
248
248
249249 $('#cancel-button').click( function () {
250250 $('#mejorar-sistema-form').fadeOut();
251251 $.mask.close();
256256 dialog = $('#mejorar-sistema-form');
257257 $('#dialog-title').empty().append('{{_("Edit resource")}}');
258258 dialog.expose({
259 closeOnClick: false,
259 closeOnClick: false,
260260 onBeforeClose: function(event) {
261261 dialog.fadeOut();
262 }
262 }
263263 });
264264 dialog.fadeIn();
265265 $('input#title').val(title);
285285 $("#resource-form1").submit();
286286 $('#mejorar-sistema-form').fadeOut();
287287 });
288
288
289289 $('#cancel-button').click( function () {
290290 $('#mejorar-sistema-form').fadeOut();
291291 $.mask.close();
296296 if (context_guid=='None') {
297297 context_guid='sugar-network'; }
298298 $('#mejorar-sistema-form').expose({
299 closeOnClick: false,
299 closeOnClick: false,
300300 onBeforeClose: function(event) {
301301 $('#mejorar-sistema-form').fadeOut();
302302 $('input#title').val('');
303303 $('input#summary').val('');
304304 $('textarea#edit-content').val('');
305 }
305 }
306306 });
307307 $('#dialog-title').empty().append('{{_('New resource')}} : {{session.get('last_context_title') or _('Sugar Network')}}')
308308 $('#mejorar-sistema-form').fadeIn();
366366 }, function() {
367367 $(".box-button", this).css('visibility', 'hidden');
368368 });
369 /* $('.grid-icon').hover( function() {
370 /* FIXME messy /
371 $(this).parent().parent().parent().find('img:first').css('background-color', '#c5c5c5');
372 $(this).parent().parent().parent().find('img:eq(1)').css('background-color', '#c5c5c5');
373 $(this).parent().parent().parent().find('img:eq(2)').css('background-color', '#c5c5c5');
374 $(this).parent().parent().parent().find('img:eq(3)').css('background-color', '#c5c5c5');
375 $(this).parent().parent().parent().find('img:eq(4)').css('background-color', '#c5c5c5');
376 $(this).parent().parent().parent().find('img:eq(5)').css('background-color', '#c5c5c5');
377 $('.button_selected').css('background-color', "#9CCEC9");
378 }, function() {
379 $(this).parent().parent().parent().find('img:first').css('background-color', inactive_color);
380 $(this).parent().parent().parent().find('img:eq(1)').css('background-color', inactive_color);
381 $(this).parent().parent().parent().find('img:eq(2)').css('background-color', inactive_color);
382 $(this).parent().parent().parent().find('img:eq(3)').css('background-color', inactive_color);
383 $(this).parent().parent().parent().find('img:eq(4)').css('background-color', inactive_color);
384 $(this).parent().parent().parent().find('img:eq(5)').css('background-color', inactive_color);
385 $('.button_selected').css('background-color', "#9CCEC9");
386 });*/
387369 $('.question-icon').css('background-color', "#D7EBF2");
388370 $('.question-icon').hover( function() {
389371 $(this).css('background-color', '#3b4ad7');
454454 });
455455 }
456456 $(document).ready( function() {
457 bind_del();
457 bind_del();
458458 $( "#sn-button" ).tooltip({position:"bottom right", offset:[-3,-60], predelay:500});
459459 $( "#browser-button" ).tooltip({position:"bottom right", offset:[-3,-60], predelay:500});
460460 $( ".has_tooltip" ).livequery( function () {
461 $( this ).tooltip({position:"bottom right", offset:[-3,-60], tipClass:"generic_tooltip",
461 $( this ).tooltip({position:"bottom right", offset:[-3,-60], tipClass:"generic_tooltip",
462462 onShow: function(event, position) {
463463 var tip = this.getTip();
464464 var new_pos = $(window).width() - (parseInt( tip.css( 'width' ), 10) + 110);
518518 location.reload();
519519 }
520520 );
521 }
521 }
522522 else {
523523 /* location='/resource/{{resource_type}}s/'+term; *
524524 location='/context/search/'+term;
  
1313 <a href="/context/reviews/{{context['guid']}}">
1414 <img class="palette-tab-button has_tooltip {{reviews}}" src="/static/icons/button-review.png" title="{{_('reviews')}}" />
1515 </a>
16 <a href="/context/gallery/{{context['guid']}}">
17 <img class="palette-tab-button has_tooltip {{gallery}}" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
18 </a>
1916 <a href="/context/all/{{context['guid']}}">
2017 <img class="palette-tab-button has_tooltip {{all}}" src="/static/icons/button-list.png" title="{{_('all resources')}}" />
2118 </a>
19 <a href="/context/gallery/{{context['guid']}}">
20 <img class="palette-tab-button has_tooltip {{gallery}}" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
21 </a>
2222 </div>
2323 <div class="grid-item context-info">
2424 <a href="/context/questions/{{context['guid']}}">
3838 </a>
3939 <a href="/context/all/{{context['guid']}}">
4040 <img class="wiki-icon has_tooltip {{all}}" src="/static/icons/button-list.png" title="{{_('all resources')}}" />
41 </a>
41 </a>
4242 <div class="iconbox has_tooltip" title="{{_('launch')}}">
4343 {%- if 'activity' in context['type'] -%}
4444 <a href="/launch/{{context['guid']}}">
4848 <img class="grid-icon" src="/context/icon/{{context['guid']}}" />
4949 </a>
5050 </div>
51 <div class="context-label">
51 <div class="context-label">
5252 <span class="context-controls">
53 <img id="moon-{{context['guid']}}"
54 title="{{_('available offline')}}"
53 <img id="moon-{{context['guid']}}"
54 title="{{_('available offline')}}"
5555 {% if context['keep_impl'] %}
5656 style="background-color:{{fill}}; border: 1px solid {{stroke}};"
5757 data-keep_impl="true"
58 {% endif %}
58 {% endif %}
5959 class="moon-emblem has_tooltip" src="/static/icons/moon.png"/>
60 <img id="star-{{context['guid']}}"
61 title="{{_('favorite')}}"
60 <img id="star-{{context['guid']}}"
61 title="{{_('favorite')}}"
6262 {% if context['keep'] %}
6363 style="background-color:{{fill}}; border: 1px solid {{stroke}};"
6464 data-keep="true"
65 {% endif %}
65 {% endif %}
6666 class="star-emblem has_tooltip" src="/static/icons/add-link-small.png"/>
6767 </span>
6868 &nbsp;
7979 </div>
8080 {%- endfor -%}
8181 </div>
82
82
8383 <h2>{{_('Summary')}}</h2>
8484 <div class="pane">{{context['summary']}}</div>
8585
9898 $('#throbber_'+guid).slideDown();
9999 $('#comments-button-'+guid).slideUp( function () {
100100 });
101 $.get('/_comments/'+guid, { resource_type:'{{resource_type}}' }, function ( data ) {
101 $.get('/_comments/'+guid, { resource_type:'{{resource_type}}' }, function ( data ) {
102102 $('#comments-'+guid).empty().append( data );
103 $('#throbber_'+guid).slideUp(
104 function() {
103 $('#throbber_'+guid).slideUp(
104 function() {
105105 $('#comments-'+guid).slideDown();
106106 });
107107 $('#comment_form_'+guid).submit(onSubmit_Comment);
133133 $('#comment_button_'+guid).slideUp();
134134 $('#comment_throbber_'+guid).slideDown();
135135 $.post( '/submit_comment',
136 $(this).serialize(),
136 $(this).serialize(),
137137 function(response) {
138138 $.get('/_comments/'+guid,
139 { resource_type:'{{resource_type}}' }, function ( data ) {
139 { resource_type:'{{resource_type}}' }, function ( data ) {
140140 $('#comment_throbber_'+guid).slideUp();
141 $('#comments-'+guid).empty().append( data );
141 $('#comments-'+guid).empty().append( data );
142142 $('#comment_form_'+guid).submit(onSubmit_Comment);
143143 initCollapse (guid);
144144 });
161161 $('#textarea-solution').slideUp();
162162 /* $('#contribute-button').attr("disabled", "disabled");*/
163163 });
164
164
165165 $('span.comments-button').click( initComments );
166166
167167 $('.solution-link').click( function() {
168 $.get($(this).data('href') + '?_pjax', {}, function ( data ) {
169 $('#resource-section').empty().append( data );
168 $.get($(this).data('href') + '?_pjax', {}, function ( data ) {
169 $('#resource-section').empty().append( data );
170170 $('span.comments-button').click( initComments );
171171 });
172172 $('#bottom-palette').slideUp();
181181 $('#bottom-palette').slideUp();
182182 };
183183
184 // When displaying notice
184 // When displaying notice
185185 if ($(".notice").length) {
186 $("#mejorar-sistema").css( "left", "49%");
187 $("#mejorar-sistema").css( "top", "40%");
186 $("#mejorar-sistema").css( "left", "49%");
187 $("#mejorar-sistema").css( "top", "40%");
188188 };
189189
190190 // When viewing resources
214214 // initialize scroll range input
215215 $("#vrange").rangeinput({vertical: true});
216216 $("#vrange").change(function(event, value) {
217 api.seekTo(value-1);
217 api.seekTo(value-1);
218218 });
219219 range_api = $("#vrange").data("rangeinput");
220220 range_api.setValue({{page}});
230230 $( '#resource-page-'+new_page ).empty().append( data );
231231 }
232232 );
233 $( '#resource-page-'+last_page ).empty().append('<div id="throbber-box"><img id="throbber" src="/static/images/throbber10.gif" /></div>');
233 $( '#resource-page-'+last_page ).empty().append('<div id="throbber-box"><img id="throbber" src="/static/images/throbber10.gif" /></div>');
234234 }
235235 last_page=new_page;
236236 load_adyacent_pages(new_page);
  
1313 <a href="/resource/reviews">
1414 <img class="palette-tab-button has_tooltip {{reviews}}" src="/static/icons/button-review.png" title="{{_('reviews')}}" />
1515 </a>
16 <a href="/resource/gallery" has_tooltip onclick='alert("{% trans %}Work in progress.{% endtrans %}"); return false;'>
17 <img class="palette-tab-button has_tooltip {{gallery}}" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
18 </a>
1916 <a href="/resource">
2017 <img class="palette-tab-button has_tooltip {{all_}} {{all}}" src="/static/icons/button-list.png" title="{{_('all resources')}}" />
2118 </a>
19 <a href="/resource/artifacts">
20 <img class="palette-tab-button has_tooltip {{gallery}}" src="/static/icons/button-blank.png" title="{{_('artifact gallery')}}" />
21 </a>
2222 </div>
2323 {#<div id="resource-buttons">
2424 <img class="question-button button{%if resource=='questions' %} selected{% endif %}" src="/static/icons/emblem-question.png" alt="Es una pregunta"/>
3434 </div>
3535 </ul>
3636 {%- endfor %}
37 {%- include('_resource-list.html') %}
37 {%- include inner_template or '_resource-list.html' %}
3838 {%- for item in range(total_pages-page) %}
3939 <ul class='resource-list' id="resource-page-{{item+page+1}}">
4040 <div id='throbber-box'>
5454 position: fixed;
5555 right: 20px;
5656 top: 150px;
57 }
57 }
5858 .handle {
5959 left:-10px;
6060 }
6565 $(".resource-list-scrollable").scrollable( {vertical:true } );
6666 var api = $("#resource-list-scrollable").data("scrollable");
6767 var last_page = {{page}};
68
68
6969 // initialize scroll range input
7070 $("#vrange").rangeinput({vertical: true});
7171 $("#vrange").change(function(event, value) {
72 api.seekTo(value-1);
72 api.seekTo(value-1);
7373 });
7474 range_api = $("#vrange").data("rangeinput");
7575 range_api.setValue({{page}});
9494 api.onSeek( function() {
9595 new_page = api.getIndex()+1;
9696 $('div.generic_tooltip').hide();
97 History.pushState(null,null,'?page=' + new_page);
97 History.pushState(null,null,'?page=' + new_page);
9898 range_api.setValue(new_page);
9999 if (new_page != last_page+1 && new_page != last_page-1) {
100100 $.get( '?page='+new_page+'&_pjax', { },
102102 $( '#resource-page-'+new_page ).empty().append( data );
103103 }
104104 );
105 $( '#resource-page-'+last_page ).empty().append('<div id="throbber-box"><img id="throbber" src="/static/images/throbber10.gif" /></div>');
105 $( '#resource-page-'+last_page ).empty().append('<div id="throbber-box"><img id="throbber" src="/static/images/throbber10.gif" /></div>');
106106 }
107107 last_page=new_page;
108108 load_adyacent_pages(new_page);
  
1717 <div id="sn-button" onclick="location='/_toggle_connect'">
1818 <span class="has_tooltip" title="{{_('connect with')}}">
1919 {% if (session['connected'] or False) %}
20 <img class="toolbar-icon sugar-network-online" src="/static/icons/sugar-network.png" />
20 <img class="toolbar-icon sugar-network-online" src="/static/icons/sugar-network.png" />
2121 {% else %}
22 <img class="toolbar-icon" src="/static/icons/sugar-network.png" />
22 <img class="toolbar-icon" src="/static/icons/sugar-network.png" />
2323 {% endif %}
2424 </span>
2525 </div>
3131 </li>
3232 <!--li class="toolbar-items" onclick="location='/favorites'">
3333 <div>
34 <img class="toolbar-icon" src="/static/icons/tool-shape-star.png" />
35 <img onclick="location='/new/resource?cursor_offset={{context_offset}}'" class="toolbar-icon white-button" src="/static/icons/list-add.png" />
34 <img class="toolbar-icon" src="/static/icons/tool-shape-star.png" />
35 <img onclick="location='/new/resource?cursor_offset={{context_offset}}'" class="toolbar-icon white-button" src="/static/icons/list-add.png" />
3636 </div>
3737 </li-->
3838 <!--li class="toolbar-items" onclick="location='/new/resource'"-->
3939 <li class="toolbar-items">
4040 <div id="browser-button" class="toolbar-button" onclick="location='/context?type=all'">
4141 <span class="has_tooltip" title="{{_('context grid')}}">
42 <img class="{{'toolbar-selected' if browser_view}} toolbar-icon" src="/static/icons/insert-table.png" />
42 <img class="{{'toolbar-selected' if browser_view}} toolbar-icon" src="/static/icons/insert-table.png" />
4343 </span>
4444 </div>
4545 <div id="browser-tooltip" class="tooltip">
5151 </li>
5252 <li class="toolbar-items">
5353 <div id="list-button" class="toolbar-button has_tooltip" onclick="location='/resource'" title="{{_('resources list')}}">
54 <img class="{{'toolbar-selected' if resource_view}} toolbar-icon" src="/static/icons/view-list.png" />
54 <img class="{{'toolbar-selected' if resource_view}} toolbar-icon" src="/static/icons/view-list.png" />
5555 </div>
5656 <!--div id="browser-tooltip" class="tooltip">
5757 <div class="menu-option" onclick="location='/resource/questions'">{{_('Questions')}}</div>
6363 </div-->
6464 </li>
6565 <li class="toolbar-items">
66 <div id="list-button" class="toolbar-button has_tooltip" onclick="location='/resource/artifacts'" title="{{_('artifacts list')}}">
67 <img class="{{'toolbar-selected' if artifacts_view}} toolbar-icon" src="/static/icons/button-blank.png" />
68 </div>
69 <!--div id="browser-tooltip" class="tooltip">
70 <div class="menu-option" onclick="location='/resource/questions'">{{_('Questions')}}</div>
71 <div class="menu-option" onclick="location='/resource/ideas'">{{_('Ideas')}}</div>
72 <div class="menu-option" onclick="location='/resource/problems'">{{_('Problems')}}</div>
73 <div class="menu-option" onclick="location='/resource/reviews'">{{_('Reviews')}}</div>
74 <hr class="menu-separator"/>
75 <div class="menu-option" onclick="location='/resource'">{{_('All')}}</div>
76 </div-->
77 </li>
78 <li class="toolbar-items">
6679 <!-- input id="search" type="text" name="terms" value="{{query or ''}}"
6780 onkeyup="onKeyPressed(event)" /-->
6881 <div class="ui-widget has_tooltip" title="{{_('type to search contexts')}}">
6982 <input id="query" name="terms" value="{{query or ''}}">
7083 </div>
7184 </li>
72 <li class="toolbar-items" onclick="improve_the_system('{{session.get('last_context')}}')">
85 <!--li class="toolbar-items" onclick="improve_the_system('{{session.get('last_context')}}')">
7386 <div class="toolbar-button has_tooltip" title="{{_('create new resource')}}">
74 <img class="toolbar-icon" src="/static/icons/list-add.png" />
87 <img class="toolbar-icon" src="/static/icons/list-add.png" />
7588 </div>
76 </li>
89 </li-->
7790 <li class="toolbar-items" onclick="new_context('{{session.get('last_context')}}')">
7891 <div class="toolbar-button has_tooltip" title="{{_('create new context')}}">
79 <img class="toolbar-icon" src="/static/icons/go-up.png" />
92 <img class="toolbar-icon" src="/static/icons/go-up.png" />
8093 </div>
8194 </li>
8295 <li class="toolbar-items" onclick="location.href='/reload'+location.pathname;">
8396 <div class="toolbar-button has_tooltip" title="{{_('reload')}}">
84 <img class="toolbar-icon" src="/static/icons/reload.png" />
97 <img class="toolbar-icon" src="/static/icons/reload.png" />
8598 </div>
8699 </li>
87100 </ul>
  
1{% extends "base.html" %}
2{% block view %}
3<div class="resource-form">
4 <div id="resource-form-title">
5 {{_('Upload an artifact: Share your work!')}}
6 <div class="window-buttons">
7 <img id="cancel-button" class="button window-button" src="/static/icons/dialog-cancel.png" />
8 </div>
9 </div>
10 {%- if (session['connected'] or False) -%}
11 <form id="resource-form1" method="POST" action="/artifacts/upload" enctype="multipart/form-data">
12 <div class="resource-form-field">
13 {{_('Context')}} : <img class="inline_images" src="/context/icon/{{context}}" /> {{session.get('last_context_title') or _('Sugar Network')}}
14 </div>
15 <div class="resource-form-field">
16 {{_('Please add a short description.')}}<br/>
17 <textarea name="content" class="resource-inputarea" ></textarea>
18 <input type="file" name="artifact_file" size="40">
19 <input type="hidden" name="context" value="{{context}}" />
20 <input type="hidden" name="implementation" value="{{implementation}}" />
21 <input type="hidden" name="filename" value="{{filename}}" />
22 </div>
23 <div class="resource-form-field">
24 <input class="sugar-button" type="submit" id="submit" value="{{_('Cargar y compartir')}}" />
25 </div>
26 <div class="resource-form-field">
27 {{_('You must use free licenses on everything you publish (conforming to Sugar Labs Licensing Policy).')}}<br/>
28 </div>
29 </form>
30 {%- else -%}
31 <div class="resource-form-field">
32 <br/>
33 <br/>
34 <b>{{_('Alpha Version')}}</b>
35 <br/>
36 {{_('For the time being you need to be connected to the Internet in order to contribute!')}}
37 </div>
38 {%- endif -%}
39</div>
40<script type="text/javascript">
41 $(function() {
42 $("#search").attr('disabled', true);
43 $("#cancel-button").click( function() {
44 history.back();
45 });
46 });
47</script>
48{% endblock view %}
  
4040
4141#from gevent.wsgi import WSGIServer
4242
43#host = '0.0.0.0' # '0.0.0.0' for all
43host = '0.0.0.0' # '0.0.0.0' for all
4444#http_server = WSGIServer((host, 5000), webui.get_app(mountset))
4545
4646#url = 'http://localhost:5000'
5151app = webui.get_app(mountset)
5252app.debug = True
5353
54app.run()
54app.run(host=host)