Skip to content
This repository
Browse code

Adding ability in the editor for a page to have multiple streams.

JS is getting fairly complex so:
* Integrated Juicer and RequireJS
* Re-organized code into widgets (html, css, and js files)
  • Loading branch information...
commit 73c818eb79e284bb5f56247813241c1465e203ce 1 parent c8227ec
Austin King authored

Showing 48 changed files with 12,517 additions and 580 deletions. Show diff stats Hide diff stats

  1. +5 1 apps/lifestream/models.py
  2. +19 4 apps/patchouli_auth/preferences.py
  3. +2 3 apps/patchouli_auth/templates/index.html
  4. +6 6 apps/patchouli_auth/views.py
  5. +1 3 apps/streamManager/templates/feed_editor.html
  6. +20 18 apps/streamManager/templates/stream_editor.html
  7. +1 1  apps/streamManager/templates/template.html
  8. +5 0 apps/streamManager/templates/widgets/add_stream_button.html
  9. +1 0  apps/streamManager/templates/widgets/delete_stream_panel.html
  10. +3 1 apps/streamManager/urls.py
  11. +54 14 apps/streamManager/views.py
  12. +5 0 bin/dev_merge.sh
  13. +5 0 bin/merge.sh
  14. +2 0  bin/verify.sh
  15. +52 0 docs/database/migrations/0.6-add-webpage-to-stream.py
  16. +143 0 static/css/editor-stylo-kitchen-sink.css
  17. +6 149 static/css/editor-stylo.css
  18. +229 0 static/css/editor-stylo.min.css
  19. +145 0 static/css/general-site-kitchen-sink.css
  20. +2 200 static/css/general-site.css
  21. +204 0 static/css/general-site.min.css
  22. +52 0 static/css/lib/reset.css
  23. +8 0 static/css/widgets/add_stream_button.css
  24. +10 0 static/css/widgets/buttons.css
  25. +7 0 static/css/widgets/delete_stream_panel.css
  26. +4 0 static/css/widgets/footer.css
  27. +33 0 static/js/README.markdown
  28. +20 17 static/js/behavior.js
  29. +32 0 static/js/effects/checkbox_disable_panel.js
  30. +20 37 static/js/feed_editor.js
  31. +1,632 0 static/js/feed_editor.min.js
  32. 0  static/js/{ → lib}/jquery-1.4.1.min.js
  33. +6,241 0 static/js/lib/jquery-1.4.2.js
  34. 0  static/js/{ → lib}/jquery-1.4.min.js
  35. 0  static/js/{ → lib}/jquery.scrollTo-min.js
  36. 0  static/js/{ → lib}/jquery.serialScroll-min.js
  37. +1,307 0 static/js/lib/require.js
  38. +93 126 static/js/stream_editor.js
  39. +1,848 0 static/js/stream_editor.min.js
  40. +30 0 static/js/widgets/#stream_editor_stream_panel.js#
  41. +1 0  static/js/widgets/.#stream_editor_stream_panel.js
  42. +56 0 static/js/widgets/add_feed_panel.js
  43. +37 0 static/js/widgets/add_stream_button.js
  44. +29 0 static/js/widgets/delete_stream_panel.js
  45. +20 0 static/js/widgets/feed_editor_delete_feed.js
  46. +30 0 static/js/widgets/stream_editor_stream_panel.js
  47. +50 0 static/js/widgets/stream_preview.js
  48. +47 0 static/js/widgets/streams/show_hide.js
6 apps/lifestream/models.py
@@ -31,6 +31,7 @@ class Stream(models.Model):
31 31 """ A stream is composed of Feeds. """
32 32 user = models.ForeignKey(User)
33 33 name = models.CharField(max_length=140)
  34 + webpage = models.ForeignKey(Webpage) # Added in 0.6 migration
34 35 # StreamConfig
35 36 config = models.TextField()
36 37 # StreamEditList
@@ -146,7 +147,10 @@ def _recent_entries(user, stream, feed_id, count=150, only_visible=True):
146 147 query = (Entry.objects.order_by('-last_published_date')
147 148 .filter(feed__user=user,
148 149 feed__url_hash=a_feed_id,
149   - feed__streams__id = stream_id))
  150 +# TODO .... Why constrain by Stream? We want to reuse feeds, right?
  151 +# the cron somehow repairs the links betwee a feed and all the streams it lives in
  152 + feed__streams__id = stream_id
  153 +))
150 154 # Visible is special, we want to see hidden items in the editor
151 155 if only_visible:
152 156 query = query.filter(streamentry__visible=True)
23 apps/patchouli_auth/preferences.py
@@ -3,6 +3,7 @@
3 3 import simplejson
4 4
5 5 import patchouli_auth.models
  6 +import lifestream.models
6 7
7 8 def getPreferences(user):
8 9 # Put all known preferences here...
@@ -60,16 +61,30 @@ def getPageProperties(page):
60 61
61 62 'processing_js': '',
62 63
63   - 'stream_names': []
  64 + 'stream_ids': []
64 65 }
65 66
66 67 existingProps = simplejson.loads(page.config)
67 68 pageProps.update(existingProps)
68   - if 0 == len(pageProps['stream_names']):
69   - # This should be page.id instead
70   - pageProps['stream_names'] = [page.name]
  69 + if 0 == len(pageProps['stream_ids']):
  70 + # Repair and save
  71 + streams = (lifestream.models.Stream.objects.all()
  72 + .order_by('id')
  73 + .filter(webpage__id = page.id))
  74 + for stream in streams:
  75 + pageProps['stream_ids'].append(stream.id)
  76 + savePageOrStreamProperties(page, pageProps)
71 77 return pageProps
72 78
  79 +def removeStreamFromPage(webpage, stream):
  80 + props = getPageProperties(webpage)
  81 + if stream.id in props['stream_ids']:
  82 + props['stream_ids'].remove(stream.id)
  83 + savePageOrStreamProperties(webpage, props)
  84 + stream.delete()
  85 + return True
  86 + return False
  87 +
73 88 def savePageOrStreamProperties(model, properties):
74 89 """ Given a Page or Stream model, persists the
75 90 properties """
5 apps/patchouli_auth/templates/index.html
@@ -44,6 +44,5 @@ <h1 class="logo"><a href="/"><strong><code>sudo</code>Social</strong></a></h1>
44 44 {% endif %}
45 45
46 46 </div><!-- /#content -->
47   -<script src="/static/js/jquery-1.4.1.min.js" type="text/javascript"></script>
48   -<script src="/static/js/stream_editor.js" type="text/javascript"></script>
49   -{% endblock %}
  47 +<script src="/static/js/stream_editor.min.js" type="text/javascript"></script>
  48 +{% endblock %}
12 apps/patchouli_auth/views.py
@@ -22,8 +22,8 @@ def account_checkauth(request):
22 22 if request.user.is_authenticated():
23 23 manageUrl = "/manage/account/%s" % request.user.username.encode('utf-8')
24 24 try:
25   - stream = lifestream.models.Stream.objects.get(user__exact=request.user)
26   - encoded_url = django.utils.encoding.iri_to_uri(manageUrl)
  25 + _ = lifestream.models.Stream.objects.all().filter(user=request.user)
  26 + encoded_url = django.utils.encoding.iri_to_uri(manageUrl)
27 27 resp = django.http.HttpResponseRedirect(encoded_url)
28 28 except lifestream.models.Stream.DoesNotExist:
29 29 log.debug("Account didn't exist")
@@ -66,7 +66,7 @@ def profile(request, username):
66 66
67 67 return render_to_response('index.html',
68 68 { 'show_delete': True,
69   - 'css_url': '/static/css/general-site.css',
  69 + 'css_url': '/static/css/general-site.min.css',
70 70 'username': request.user.username,
71 71 'email': request.user.email,
72 72
@@ -92,7 +92,7 @@ def delete_profile(request, username):
92 92 else:
93 93 return render_to_response('confirm_delete.html',
94 94 {
95   - 'css_url': '/static/css/general-site.css',
  95 + 'css_url': '/static/css/general-site.min.css',
96 96 'lang_dir': 'LTR',
97 97 'page_lang': 'en',
98 98 },
@@ -135,7 +135,7 @@ def confirm_profile(request):
135 135 avatar_url = "http://www.gravatar.com/avatar/%s.jpg?d=monsterid&s=80" % gravatarHash
136 136
137 137 return render_to_response('index.html',
138   - { 'css_url': '/static/css/general-site.css',
  138 + { 'css_url': '/static/css/general-site.min.css',
139 139 'username': request.user.username,
140 140 'email': request.user.email,
141 141
@@ -172,4 +172,4 @@ def session_status(request):
172 172 amstatus = "none;"
173 173 resp = django.http.HttpResponse("X-Account-Managment-Status will be %s" % amstatus)
174 174 resp['X-Account-Management-Status'] = amstatus
175   - return resp
  175 + return resp
4 apps/streamManager/templates/feed_editor.html
@@ -46,7 +46,5 @@
46 46
47 47 </div><!-- #feed_preview -->
48 48 </div><!-- #feed_panel -->
49   - <script type="text/javascript" src="/static/js/jquery-1.4.1.min.js"></script>
50   - <script src="/static/js/feed_editor.js" type="text/javascript"></script>
51   - <script src="/static/js/stream_editor.js" type="text/javascript"></script>
  49 + <script src="/static/js/feed_editor.min.js" type="text/javascript"></script>
52 50 {% endblock %}
38 apps/streamManager/templates/stream_editor.html
@@ -6,37 +6,41 @@
6 6 <li>New Page</li>
7 7 <li>All Pages</li>
8 8 </ul>
9   -
  9 + {% include 'widgets/add_stream_button.html' %}
10 10 {% endblock %}
11 11
12 12 {% block content %}
13 13 <h1>Stream Editor</h1>
14 14 <div id="stream-editor-panel" lang="{{page_props.page_lang}}" dir="{{page_props.page_lang_dir}}">
15 15 <ul class="tabs">
16   - <li id="edit-stream" class="tab editor"><a href="#">Edit </a>{% if first_stream %}<strong id="stream{{first_stream.id}}" class="stream-name">{{first_stream.name}}</strong> Stream Page{% endif %}</li>
  16 + <!-- TODO: Is stream1 used ? (first_stream.id). Change to page.id ? -->
  17 + <li id="edit-stream" class="tab editor"><a href="#">Edit </a>{% if first_stream %}<strong id="stream{{first_stream.id}}" class="page-name">{{page_name}}</strong> Stream Page{% endif %}</li>
17 18 <li id="design-stream" class="tab design xactive-tab"><a href="#">Design</a></li>
18 19 <li id="page-widgets" class="tab pagewidget active-tab"><a href="#">Page Widgets</a></li>
19   - {% if first_stream %}<li><a id="preview" href="/u/{{username}}/s/{{first_stream.name}}" target="_new" title="View your currenly published Stream in a new window">View</a></li>{% endif %}
  20 + {% if first_stream %}<li><a id="preview" href="/u/{{username}}/s/{{page_name}}" target="_new" title="View your currenly published Stream in a new window">View</a></li>{% endif %}
20 21 </ul>
21 22 <!--------------------- Edit Stream Panel ------------------------->
22 23 <div id="edit-stream-panel" class="panel">
  24 +
  25 +
23 26 {% for stream in streams %}
24 27 <div class="streams-panel"><!-- streams panel contains the metadata and preview -->
25 28 <div class="stream-metadata-panel">
26 29 <h2 class="new-feed">Add A Source</h2>
27 30 <p>Paste in the Url to a website or any Atom or RSS feed <img src="/static/img/feed-icon-14x14.png" width="14" height="14" alt="Feed Icon" />.</p>
28 31
29   - <form id="add-url-form" action="/manage/urls/{{request.user.username}}" method="post">
30   - <p><label for="id_url">Url:</label> <input id="id_url" type="text" name="url" maxlength="2048" /></p>
  32 + <form class="add-url-form" action="/manage/urls/{{request.user.username}}" method="post">
  33 + <p><label for="id_url">Url:</label> <input class="id_url" type="text" name="url" maxlength="2048" /></p>
31 34 <p>
32 35 <label for="id_streams">Streams:</label>
33   - <input type="hidden" name="streams" id="id_streams" value="{{stream.name}}" /></p>
  36 + <!-- TODO test add feed form -->
  37 + <input type="hidden" name="streams" class="id_streams" value="{{stream.id}}" /></p>
34 38 <input type="submit" value="Add Feed" />
35 39 </p>
36 40 </form>
37 41
38 42 <h2>Stream Sources</h2>
39   - <ul id="user_streams">
  43 + <ul class="user_streams">
40 44 {% for feed in stream.feeds %}
41 45 <li>
42 46 <a href="{{ feed.url }}" class="stream-feed-source"> {% if feed.title %}{{ feed.title }}{% else %} {{ feed.url }} {% endif %}</a>
@@ -44,23 +48,22 @@ <h2 class="new-feed">Add A Source</h2>
44 48 <a href="/manage/account/{{username}}/stream/{{stream.id}}/feed/{{feed.pk}}" class="button">Edit</a>
45 49 </li>
46 50 {% empty %}
47   - <li id="no-stream-feed-blurb"><a href="#" class="stream-feed-source"></a><a href="{{ feed.pk }}" class="feed-delete" title="Delete this feed."></a>You have no stream sources, add a new feed.</li>
  51 + <li class="no-stream-feed-blurb"><a href="#" class="stream-feed-source"></a>You have no stream sources, add a new feed.
  52 + <!-- Empty case we have to add the stream and feed ids... and show -->
  53 + <a href="/manage/account/{{username}}/stream/" class="button" style="display:none">Edit</a></li>
48 54 {% endfor %}
49 55
50   - <li id="base-stream-feed-link" style="display:none"><a href="{{ feed.url }}" class="stream-feed-source">sample</a>
51   - <div class="feed-entries-visible-default shown" title="New Items are shown automatically"></div>
52   - <a href="#" class="feed-edit" title="Edit this feed.">Edit</a></li>
  56 + <li class="base-stream-feed-link" style="display:none"><a href="{{ feed.url }}" class="stream-feed-source">sample</a>
  57 + <a href="#" class="feed-edit button" title="Edit this feed.">Edit</a></li>
53 58 </ul>
54   - <p>After 5 minutes, Feed entries should start appearing in <a href="/u/{{username}}/s/{{stream.name}}" target="_new" title="View your currenly published Stream in a new window">your stream.</a></p>
  59 + <p>After 5 minutes, Feed entries should start appearing in <a href="/u/{{username}}/s/{{page_name}}" target="_new" title="View your currenly published Stream in a new window">your stream.</a></p>
  60 + {% include 'widgets/delete_stream_panel.html' %}
55 61 </div><!-- /.stream-metadata-panel -->
56 62 <div class="stream-preview-panel">
57 63 {% include 'feed_editor_preview.html' %}
58 64 </div><!-- /.stream-preview-panel -->
59 65 </div><!-- /.streams-panel -->
60 66 {% endfor %}
61   - <!-- div class="add-stream-panel">
62   - <p class="callout">A page can have multiple streams. <a href="#todo" class="button">Add Another Stream</a>.</p>
63   - </div -->
64 67 </div><!-- /#edit-stream-panel -->
65 68
66 69 <!--------------------- Page Widgets Panel ------------------------->
@@ -132,7 +135,7 @@ <h2 class="new-feed">Add A Source</h2>
132 135 </div><!-- /optional-widget -->
133 136
134 137 <div class="stream-icon">
135   - <h3>Your {{stream.name}} Stream</h3>
  138 + <h3>Your {{page_name}} Stream</h3>
136 139 <img src="/static/img/StreamDiagram_25perc.jpg" width="76" height="95" />
137 140 </div>
138 141
@@ -212,6 +215,5 @@ <h2 class="new-feed">Add A Source</h2>
212 215 </div><!-- /design-stream -->
213 216 </div><!-- /stream-editor-panel -->
214 217
215   -<script src="/static/js/jquery-1.4.1.min.js" type="text/javascript"></script>
216   -<script src="/static/js/stream_editor.js" type="text/javascript"></script>
  218 +<script src="/static/js/stream_editor.min.js" type="text/javascript"></script>
217 219 {% endblock %}
2  apps/streamManager/templates/template.html
@@ -4,7 +4,7 @@
4 4 <head>
5 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
6 6 <title>{% block title %}SudoSocial{% endblock %}</title>
7   - <link href="/static/css/editor-stylo.css" type="text/css" rel="stylesheet">
  7 + <link href="/static/css/editor-stylo.min.css" type="text/css" rel="stylesheet">
8 8 {%block page_css_link %} {% endblock %}
9 9 <link rel="icon" href="/static/img/favicon.png" type="image/png">
10 10 </head>
5 apps/streamManager/templates/widgets/add_stream_button.html
... ... @@ -0,0 +1,5 @@
  1 +<div class="add-stream-panel">
  2 + <p class="callout">A page can have multiple streams.</p>
  3 + <p><a href="/manage/streams/{{username}}/p/{{page_name}}" class="add-stream button">Add Another Stream</a>.</p>
  4 + <p class="creating">Creating Stream</p>
  5 +</div>
1  apps/streamManager/templates/widgets/delete_stream_panel.html
... ... @@ -0,0 +1 @@
  1 +<p class="stream-delete-panel"><a href="{{stream.id}}" class="stream-delete button">Delete</a></p>
4 apps/streamManager/urls.py
@@ -6,7 +6,9 @@
6 6 (r'^account/(?P<username>\w+)/stream/(?P<stream_id>\d+)/preview_feed/(?P<feed_id>\w+)$', 'views.preview_feed'),
7 7 (r'^stream/design$', 'views.manage_page_design'),
8 8 (r'^stream/(?P<username>\w+)/s/(?P<page_name>\w+)$', 'views.manage_page'),
9   -
  9 + (r'^stream/(?P<username>\w+)/sid/(?P<stream_id>\w+)$', 'views.stream'),
  10 + (r'^streams/(?P<username>\w+)/p/(?P<page_name>\w+)$', 'views.streams', {}, 'streams'),
  11 +
10 12 (r'^page/(?P<page_name>\w+)$', 'views.manage_page_widgets'),
11 13
12 14 (r'^urls/(?P<username>\w+)$', 'views.urls'),
68 apps/streamManager/views.py
... ... @@ -1,6 +1,7 @@
1 1 import logging
2 2 import datetime
3 3 import hashlib
  4 +import time
4 5
5 6 import feedparser
6 7 from pyquery import PyQuery
@@ -39,11 +40,11 @@ def manage_profile(request):
39 40 @login_required
40 41 def manage(request, username):
41 42 if request.user.username == username:
42   - streams = lifestream.models.Stream.objects.filter(user=request.user).all()
43   - if len(streams) == 1:
44   - return manage_page(request, username, 'home')
  43 + pages = lifestream.models.Webpage.objects.filter(user=request.user).all()
  44 + if len(pages) == 1:
  45 + return manage_page(request, username, pages[0].name)
45 46 else:
46   - return manage_all_streams(request, username)
  47 + return manage_all_pages(request, username)
47 48 else:
48 49 return django.http.HttpResponse(HACKING_MESSAGE, status=400)
49 50
@@ -54,11 +55,12 @@ def entry_pair_for_entries(request, raw_entries, plugins):
54 55 @login_required
55 56 def manage_page(request, username, page_name):
56 57 if request.user.username == username:
  58 + log.info("Grabbing webpage")
57 59 webpage = get_object_or_404(lifestream.models.Webpage, user=request.user, name=page_name)
58 60 webpage_properties = patchouli_auth.preferences.getPageProperties(webpage)
59 61 streams = []
60   - for stream_name in webpage_properties['stream_names']:
61   - stream = get_object_or_404(lifestream.models.Stream, user=request.user, name=stream_name)
  62 + for stream_id in webpage_properties['stream_ids']:
  63 + stream = get_object_or_404(lifestream.models.Stream, user=request.user, id=stream_id)
62 64 streams.append(stream)
63 65 stream_config = StreamConfig(stream.config)
64 66 feed_rows = stream.feed_set.all()
@@ -127,7 +129,7 @@ def manage_page(request, username, page_name):
127 129 'page_langs': lang.HTML_LANG,
128 130 'page_lang_desc': lang.HTML_LANG[webpage_properties['page_lang']],
129 131 'page_lang_dirs': lang.DIR_CHOICES,
130   - 'page_name': stream.name,
  132 + 'page_name': page_name,
131 133 'request': request,
132 134 'streams': streams,
133 135 'stream_id': stream.id,
@@ -210,8 +212,11 @@ def append_if_dict(a_list, maybe_dict):
210 212 def save_feeds(request, username):
211 213 new_feeds_to_save = []
212 214 params = request.POST.copy()
213   - stream = get_object_or_404(lifestream.models.Stream, user=request.user,
214   - name=params['streams[]'])
  215 + log.info("Saving for stream with an id of")
  216 + log.info(params['streams[]'])
  217 + stream = get_object_or_404(lifestream.models.Stream,
  218 + user=request.user,
  219 + id=params['streams[]'])
215 220 feed_url = request.POST['url']
216 221 possible_feed = is_possible_feed(feed_url)
217 222 if possible_feed:
@@ -232,7 +237,7 @@ def save_feeds(request, username):
232 237 a_feed = lifestream.models.Feed(url_hash = feed_url_hash, title=new_feed_to_save['feed_title'],
233 238 url = new_feed_to_save['feed_url'],
234 239 etag='', last_modified=datetime.datetime(1975, 1, 10),
235   - enabled=True, disabled_reason='',
  240 + enabled=True, disabled_reason='',
236 241 user=request.user, created_date=datetime.datetime.today())
237 242 a_feed.streams.add(stream)
238 243 form = lifestream.models.FeedForm(params, instance=a_feed)
@@ -494,25 +499,60 @@ def preview_feed(request, username, stream_id, feed_id):
494 499 'stream_id': stream.id,
495 500 },
496 501 context_instance=django.template.RequestContext(request))
497   -
  502 +@login_required
  503 +def streams(request, username, page_name):
  504 + if request.user.username == username:
  505 + if 'POST' == request.method:
  506 + webpage = get_object_or_404(lifestream.models.Webpage, user=request.user, name=page_name)
  507 + webpage_props = patchouli_auth.preferences.getPageProperties(webpage)
  508 + new_stream_name = "Untitled %d" % int(time.mktime(datetime.datetime.now().timetuple()) * 1000)
  509 + new_stream = lifestream.models.Stream(user=request.user, name=new_stream_name, webpage=webpage)
  510 + new_stream.save()
  511 +
  512 + webpage_props['stream_ids'].append(new_stream.id)
  513 + patchouli_auth.preferences.savePageOrStreamProperties(webpage, webpage_props)
  514 + payload = {'status': 'OK', 'new_stream_id': new_stream.id}
  515 + #TODO type in all these content-types.... WTF?
  516 + return django.http.HttpResponse(json.dumps(payload), mimetype='applicaiton/json')
  517 +
  518 + else:
  519 + return django.http.HttpResponse('Hey')
  520 + else:
  521 + return django.http.HttpResponse('{"message":"' + HACKING_MESSAGE + '"}', mimetype='applicaiton/json', status=400)
  522 +
  523 +@login_required
  524 +def stream(request, username, stream_id):
  525 + if request.user.username == username:
  526 + if 'DELETE' == request.method:
  527 + stream = get_object_or_404(lifestream.models.Stream, user=request.user, id=stream_id)
  528 + payload = {'status': 'ERROR', 'msg': 'Unabled to remove stream'}
  529 + log.info("Removing stream %d %s" % (stream.id, stream.name))
  530 + if patchouli_auth.preferences.removeStreamFromPage(stream.webpage, stream):
  531 + payload = {'status': 'OK', 'msg': 'Stream removed'}
  532 + return django.http.HttpResponse(json.dumps(payload), mimetype='applicaiton/json')
  533 + else:
  534 + return django.http.HttpResponse('Hey')
  535 + else:
  536 + return django.http.HttpResponse('{"message":"' + HACKING_MESSAGE + '"}', mimetype='applicaiton/json', status=400)
  537 +
498 538 # ----------------- Sitewide Functions --------------#
499 539 def homepage(request):
500 540 return render_to_response('homepage.html',
501   - {'css_url': '/static/css/general-site.css',
  541 + {'css_url': '/static/css/general-site.min.css',
502 542 'lang_dir': 'LTR',
503 543 'page_lang': 'en',},
504 544 context_instance=django.template.RequestContext(request))
505 545
506 546 def page_not_found(request):
507 547 response = render_to_response('404.html',
508   - {'css_url': '/static/css/general-site.css'},
  548 + {'css_url': '/static/css/general-site.min.css'},
509 549 context_instance=django.template.RequestContext(request))
510 550 response.status_code = 404
511 551 return response
512 552
513 553 def server_error(request):
514 554 response = render_to_response('500.html',
515   - {'css_url': '/static/css/general-site.css'},
  555 + {'css_url': '/static/css/general-site.min.css'},
516 556 context_instance=django.template.RequestContext(request))
517 557 response.status_code = 500
518 558 return response
5 bin/dev_merge.sh
... ... @@ -0,0 +1,5 @@
  1 +juicer merge -s --force -m '' static/js/stream_editor.js
  2 +juicer merge -s --force -m '' static/js/feed_editor.js
  3 +
  4 +juicer merge -d . -e data_uri -f -m '' static/css/editor-stylo.css
  5 +juicer merge -d . -e data_uri -f -m '' static/css/general-site.css
5 bin/merge.sh
... ... @@ -0,0 +1,5 @@
  1 +juicer merge -s --force static/js/stream_editor.js
  2 +juicer merge -s --force static/js/feed_editor.js
  3 +
  4 +juicer merge -d . -e data_uri -f static/css/editor-stylo.css
  5 +juicer merge -d . -e data_uri -f static/css/general-site.css
2  bin/verify.sh
... ... @@ -0,0 +1,2 @@
  1 +find static/js/ -name '[a-zA-Z]*.js' | grep -v "/lib/" | grep -v "min.js" | xargs juicer verify
  2 +
52 docs/database/migrations/0.6-add-webpage-to-stream.py
... ... @@ -0,0 +1,52 @@
  1 +"""
  2 + Run python manage.py dbsync
  3 + Then run this migration
  4 + Create a config.py based off of config.py.dist in this directory... then run as
  5 + python docs/database/migrations/0.5-split-entry.py
  6 +"""
  7 +import sys
  8 +
  9 +import config
  10 +sys.path.append(config.path)
  11 +
  12 +from django.core.management import setup_environ
  13 +import settings
  14 +setup_environ(settings)
  15 +
  16 +import os
  17 +import site
  18 +
  19 +ROOT = os.path.dirname(os.path.abspath(__file__))
  20 +path = lambda *a: os.path.join(ROOT, *a)
  21 +site.addsitedir(path('../../../apps'))
  22 +
  23 +import logging
  24 +logging.basicConfig(level = config.log_level,
  25 + format = '%(asctime)s %(levelname)s %(process)d %(message)s', )
  26 +log = logging.getLogger()
  27 +
  28 +log.info("Added %s" % path('../../../apps'))
  29 +
  30 +from django.db import connection, transaction
  31 +cursor = connection.cursor()
  32 +
  33 +log.info("So far so good so what")
  34 +log.info(sys.path)
  35 +
  36 +from lifestream.models import Webpage, Stream
  37 +
  38 +log.info("Adding webpage_id column")
  39 +cursor.execute("ALTER TABLE lifestream_stream ADD COLUMN webpage_id integer NOT NULL")
  40 +log.info("Adding foreign key constraint")
  41 +cursor.execute("ALTER TABLE `lifestream_stream` ADD CONSTRAINT `webpage_id_refs_id_6804d8c3` FOREIGN KEY (`webpage_id`) REFERENCES `lifestream_webpage` (`id`)")
  42 +
  43 +transaction.commit_unless_managed()
  44 +
  45 +for stream in Stream.objects.all():
  46 + webpage = Webpage.objects.get(user__id = stream.user_id,
  47 + name='home')
  48 + stream.webpage_id = webpage.id
  49 + stream.save()
  50 +
  51 +#transaction.commit_unless_managed()
  52 +log.info("Done success")
143 static/css/editor-stylo-kitchen-sink.css
... ... @@ -0,0 +1,143 @@
  1 +/* TODO break up into chunks and @import from editor-stylo.css */
  2 +
  3 +div.logo a {
  4 + padding-left: 67px;
  5 + background-image: url('/static/img/riverdam_logo_62x35.jpg?embed=true');
  6 + background-repeat: no-repeat;
  7 +}
  8 +div.logo {
  9 + font-size: 300%;
  10 + line-height: 1;
  11 +}
  12 +div.logo, div.logo a {
  13 + color: #1046b0;
  14 + font-weight: bold;
  15 + text-decoration: none;
  16 +}
  17 +.tagline {
  18 + font-size: 110%;
  19 + font-style: italic;
  20 + line-height: 1;
  21 + margin-top: 0px;
  22 + padding-top: 0px;
  23 + float: left;
  24 +}
  25 +.logo-panel { float: left; }
  26 +.logo-panel .logo { font-size: 200%; float: left; }
  27 +.logo-panel .tagline { font-size: 90%; line-height: 3.0; }
  28 +
  29 +#auth {
  30 +
  31 + float: right;
  32 + padding: 0.3em;
  33 +}
  34 +#heading {
  35 +
  36 + width: 100%;
  37 +}
  38 +#sidebar {
  39 + position: absolute;
  40 + width: 200px;
  41 +}
  42 +#content {
  43 + margin-left: 180px;
  44 +}
  45 +#content > h1:first {
  46 + padding-top: 0px;
  47 + margin-top: -30px;
  48 + clear: both;
  49 +}
  50 +#edit-stream-panel {
  51 + float: left;
  52 + width: 800px;
  53 +}
  54 +#feed_panel { width: 1030px; }
  55 +.streams-panel { float: left; width: 815px; border: dotted 1px grey; } /* contains .stream-metadata-panel and .stream-preview-panel */
  56 +
  57 +.stream-metadata-panel { width: 300px; float: left; }
  58 +.stream-preview-panel, #stream-preview { width: 500px; float: left; overflow: scroll; margin-left: 5px; padding-right: 10px;}
  59 +
  60 +.feed-entry hr { display: none; }
  61 +.feed-entry {
  62 + border: solid 1px #666;
  63 + border-top: solid 3px #333;
  64 + border-right: solid 2px #333;
  65 +
  66 + -moz-border-radius: 3px;
  67 + -webkit-border-radius: 3px;
  68 + margin-bottom: 10px;
  69 + max-height: 400px;
  70 +
  71 + overflow: auto;
  72 + padding: 5px;
  73 +}
  74 +
  75 + .tabs li {
  76 +
  77 + float: left;
  78 + margin-right: 0.5em;
  79 + padding: 0.2em 0.5em;
  80 + list-style: none;
  81 +
  82 + z-index: 2;
  83 + }
  84 + .tabs li.tab {
  85 + background-color: #EEE;
  86 + border: solid 1px #000;
  87 + }
  88 +
  89 + .tabs li.active-tab {
  90 + border-bottom: none;
  91 + background-color: #FFF;
  92 + }
  93 + .panel { border: solid 1px #CCC; clear: left; position: relative; top: -1px; z-index: 1; padding: 0em 1em;}
  94 + h2 { clear: left;}
  95 +#other-sources-panel {
  96 +
  97 + width: 300px;
  98 + float: right;
  99 +}
  100 +#design-stream-panel .save, #page-widgets-panel .save { float: right; margin: 1em 1em 0em 0em }/* text-align: right; */
  101 +
  102 +#page-widgets-panel label { font-weight: bold; font-size: 115%; }
  103 +#page-widgets-panel textarea { width: 600px; height: 300px; margin:10px}
  104 +#page-widgets-panel strong { display: block; }
  105 +.checkbox-label {font-weight: bold;}
  106 +#page-widgets-panel label.checkbox {font-weight: normal; font-size: 100%;}
  107 +br, .optional-widget { clear: both; }
  108 +
  109 +.display_entry {
  110 + float: right;
  111 +}
  112 +
  113 +.feed-entries-visible-default {
  114 + width: 16px;
  115 + height: 16px;
  116 + border: 1px solid #333;
  117 + display: inline-table;
  118 +}
  119 +feed-entries-visible-default.hidden {
  120 + background-color: #666;
  121 +}
  122 +feed-entries-visible-default.shown {
  123 + background-color: #CCC;
  124 +}
  125 +div.entry-hidden {
  126 + background-color: #CCC;
  127 + color: #333;
  128 +}
  129 +fieldset, .field {
  130 + -moz-border-radius: 5px;
  131 + -webkit-border-radius: 5px;
  132 + border: 1px solid #000;
  133 + margin: 10px auto 10px auto;
  134 + padding: 10px;
  135 + width: 650px;
  136 +}
  137 +#manage-page-widgets fieldset,
  138 +.optional-text-widget { margin-left: 0px; margin-right: 0px; }
  139 +input.url {
  140 + width: 600px;
  141 +}
  142 +
  143 +.user_streams li { line-height: 2.2em; }
155 static/css/editor-stylo.css
... ... @@ -1,154 +1,11 @@
  1 +@import url("lib/reset.css")
1 2
2   -div.logo a {
3   - padding-left: 67px;
4   - background-image: url('/static/img/riverdam_logo_62x35.jpg');
5   - background-repeat: no-repeat;
6   -}
7   -div.logo {
8   - font-size: 300%;
9   - line-height: 1;
10   -}
11   -div.logo, div.logo a {
12   - color: #1046b0;
13   - font-weight: bold;
14   - text-decoration: none;
15   -}
16   -.tagline {
17   - font-size: 110%;
18   - font-style: italic;
19   - line-height: 1;
20   - margin-top: 0px;
21   - padding-top: 0px;
22   - float: left;
23   -}
24   -.logo-panel { float: left; }
25   -.logo-panel .logo { font-size: 200%; float: left; }
26   -.logo-panel .tagline { font-size: 90%; line-height: 3.0; }
  3 +@import url("editor-stylo-kitchen-sink.css")
27 4
28   -#auth {
29   -
30   - float: right;
31   - padding: 0.3em;
32   -}
33   -#heading {
  5 +@import url("widgets/buttons.css")
34 6
35   - width: 100%;
36   -}
37   -#sidebar {
38   - position: absolute;
39   - width: 200px;
40   -}
41   -#content {
42   - margin-left: 180px;
43   -}
44   -#content > h1:first {
45   - padding-top: 0px;
46   - margin-top: -30px;
47   - clear: both;
48   -}
49   -#edit-stream-panel {
50   - float: left;
51   - width: 800px;
52   -}
53   -#feed_panel { width: 1030px; }
54   -.streams-panel, .add-stream-panel { float: left; width: 815px; border: dotted 1px grey; } /* contains .stream-metadata-panel and .stream-preview-panel */
55   -.add-stream-panel { width: 300px; }
56   -.stream-metadata-panel { width: 300px; float: left; }
57   -.stream-preview-panel, #stream-preview { width: 500px; float: left; overflow: scroll; margin-left: 5px; padding-right: 10px;}
58   -.callout {
59   - line-height: 2.5;
60   - margin-left: 10px;
61   -}
62   -.feed-entry hr { display: none; }
63   -.feed-entry {
64   - border: solid 1px #666;
65   - border-top: solid 3px #333;
66   - border-right: solid 2px #333;
67   -
68   - -moz-border-radius: 3px;
69   - -webkit-border-radius: 3px;
70   - margin-bottom: 10px;
71   - max-height: 400px;
72   -
73   - overflow: auto;
74   - padding: 5px;
75   -}
  7 +@import url("widgets/add_stream_button.css");
76 8
77   - .tabs li {
78   -
79   - float: left;
80   - margin-right: 0.5em;
81   - padding: 0.2em 0.5em;
82   - list-style: none;
83   -
84   - z-index: 2;
85   - }
86   - .tabs li.tab {
87   - background-color: #EEE;
88   - border: solid 1px #000;
89   - }
90   -
91   - .tabs li.active-tab {
92   - border-bottom: none;
93   - background-color: #FFF;
94   - }
95   - .panel { border: solid 1px #CCC; clear: left; position: relative; top: -1px; z-index: 1; padding: 0em 1em;}
96   - h2 { clear: left;}
97   -#other-sources-panel {
  9 +@import url("widgets/delete_stream_panel.css");
98 10
99   - width: 300px;
100   - float: right;
101   -}
102   -#design-stream-panel .save, #page-widgets-panel .save { float: right; margin: 1em 1em 0em 0em }/* text-align: right; */
103   -
104   -#page-widgets-panel label { font-weight: bold; font-size: 115%; }
105   -#page-widgets-panel textarea { width: 600px; height: 300px; margin:10px}
106   -#page-widgets-panel strong { display: block; }
107   -.checkbox-label {font-weight: bold;}
108   -#page-widgets-panel label.checkbox {font-weight: normal; font-size: 100%;}
109   -br, .optional-widget { clear: both; }
110   -
111   -.display_entry {
112   - float: right;
113   -}
114   -
115   -.feed-entries-visible-default {
116   - width: 16px;
117   - height: 16px;
118   - border: 1px solid #333;
119   - display: inline-table;
120   -}
121   -feed-entries-visible-default.hidden {
122   - background-color: #666;
123   -}
124   -feed-entries-visible-default.shown {
125   - background-color: #CCC;
126   -}
127   -div.entry-hidden {
128   - background-color: #CCC;
129   - color: #333;
130   -}
131   -fieldset, .field {
132   - -moz-border-radius: 5px;
133   - -webkit-border-radius: 5px;
134   - border: 1px solid #000;
135   - margin: 10px auto 10px auto;
136   - padding: 10px;
137   - width: 650px;
138   -}
139   -#manage-page-widgets fieldset,
140   -.optional-text-widget { margin-left: 0px; margin-right: 0px; }
141   -input.url {
142   - width: 600px;
143   -}
144   -
145   -#user_streams li { line-height: 2.2em; }
146   -
147   -.button {
148   - background-color: #DDD;
149   - color: #000;
150   - border: solid 1px grey;
151   - padding: 5px 10px;
152   - -moz-border-radius: 15px;
153   - border-radius: 15px;
154   -}
  11 +@import url("widgets/footer.css");
229 static/css/editor-stylo.min.css
... ... @@ -0,0 +1,229 @@
  1 +/* v1.0 | 20080212 */
  2 +
  3 +html, body, div, span, applet, object, iframe,
  4 +h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  5 +a, abbr, acronym, address, big, cite, code,
  6 +del, dfn, em, font, img, ins, kbd, q, s, samp,
  7 +small, strike, strong, sub, sup, tt, var,
  8 +b, u, i, center,
  9 +dl, dt, dd, ol, ul, li,
  10 +fieldset, form, label, legend,
  11 +table, caption, tbody, tfoot, thead, tr, th, td {
  12 + margin: 0;
  13 + padding: 0;
  14 + border: 0;
  15 + outline: 0;
  16 + font-size: 100%;
  17 + vertical-align: baseline;
  18 + background: transparent;
  19 +}
  20 +body {
  21 + line-height: 1;
  22 +}
  23 +ol, ul {
  24 + list-style: none;
  25 +}
  26 +blockquote, q {
  27 + quotes: none;
  28 +}
  29 +blockquote:before, blockquote:after,
  30 +q:before, q:after {
  31 + content: '';
  32 + content: none;
  33 +}
  34 +
  35 +/* remember to define focus styles! */
  36 +:focus {
  37 + outline: 0;
  38 +}
  39 +
  40 +/* remember to highlight inserts somehow! */
  41 +ins {
  42 + text-decoration: none;
  43 +}
  44 +del {
  45 + text-decoration: line-through;
  46 +}
  47 +
  48 +/* tables still need 'cellspacing="0"' in the markup */
  49 +table {
  50 + border-collapse: collapse;
  51 + border-spacing: 0;
  52 +}
  53 +/* TODO break up into chunks and @import from editor-stylo.css */
  54 +
  55 +div.logo a {
  56 + padding-left: 67px;
  57 + background-image: url('data:image/jpg;base64,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');
  58 + background-repeat: no-repeat;
  59 +}
  60 +div.logo {
  61 + font-size: 300%;
  62 + line-height: 1;
  63 +}
  64 +div.logo, div.logo a {
  65 + color: #1046b0;
  66 + font-weight: bold;
  67 + text-decoration: none;
  68 +}
  69 +.tagline {
  70 + font-size: 110%;
  71 + font-style: italic;
  72 + line-height: 1;
  73 + margin-top: 0px;
  74 + padding-top: 0px;
  75 + float: left;
  76 +}
  77 +.logo-panel { float: left; }
  78 +.logo-panel .logo { font-size: 200%; float: left; }
  79 +.logo-panel .tagline { font-size: 90%; line-height: 3.0; }
  80 +
  81 +#auth {
  82 +
  83 + float: right;
  84 + padding: 0.3em;
  85 +}
  86 +#heading {
  87 +
  88 + width: 100%;
  89 +}
  90 +#sidebar {
  91 + position: absolute;
  92 + width: 200px;
  93 +}
  94 +#content {
  95 + margin-left: 180px;
  96 +}
  97 +#content > h1:first {
  98 + padding-top: 0px;
  99 + margin-top: -30px;
  100 + clear: both;
  101 +}
  102 +#edit-stream-panel {
  103 + float: left;
  104 + width: 800px;
  105 +}
  106 +#feed_panel { width: 1030px; }
  107 +.streams-panel { float: left; width: 815px; border: dotted 1px grey; } /* contains .stream-metadata-panel and .stream-preview-panel */
  108 +
  109 +.stream-metadata-panel { width: 300px; float: left; }
  110 +.stream-preview-panel, #stream-preview { width: 500px; float: left; overflow: scroll; margin-left: 5px; padding-right: 10px;}
  111 +
  112 +.feed-entry hr { display: none; }
  113 +.feed-entry {
  114 + border: solid 1px #666;
  115 + border-top: solid 3px #333;
  116 + border-right: solid 2px #333;
  117 +
  118 + -moz-border-radius: 3px;
  119 + -webkit-border-radius: 3px;
  120 + margin-bottom: 10px;
  121 + max-height: 400px;
  122 +
  123 + overflow: auto;
  124 + padding: 5px;
  125 +}
  126 +
  127 + .tabs li {
  128 +
  129 + float: left;
  130 + margin-right: 0.5em;
  131 + padding: 0.2em 0.5em;
  132 + list-style: none;
  133 +
  134 + z-index: 2;
  135 + }
  136 + .tabs li.tab {
  137 + background-color: #EEE;
  138 + border: solid 1px #000;
  139 + }
  140 +
  141 + .tabs li.active-tab {
  142 + border-bottom: none;
  143 + background-color: #FFF;
  144 + }
  145 + .panel { border: solid 1px #CCC; clear: left; position: relative; top: -1px; z-index: 1; padding: 0em 1em;}
  146 + h2 { clear: left;}
  147 +#other-sources-panel {
  148 +
  149 + width: 300px;
  150 + float: right;
  151 +}
  152 +#design-stream-panel .save, #page-widgets-panel .save { float: right; margin: 1em 1em 0em 0em }/* text-align: right; */
  153 +
  154 +#page-widgets-panel label { font-weight: bold; font-size: 115%; }
  155 +#page-widgets-panel textarea { width: 600px; height: 300px; margin:10px}
  156 +#page-widgets-panel strong { display: block; }
  157 +.checkbox-label {font-weight: bold;}
  158 +#page-widgets-panel label.checkbox {font-weight: normal; font-size: 100%;}
  159 +br, .optional-widget { clear: both; }
  160 +
  161 +.display_entry {
  162 + float: right;
  163 +}
  164 +
  165 +.feed-entries-visible-default {
  166 + width: 16px;
  167 + height: 16px;
  168 + border: 1px solid #333;
  169 + display: inline-table;
  170 +}
  171 +feed-entries-visible-default.hidden {
  172 + background-color: #666;
  173 +}
  174 +feed-entries-visible-default.shown {
  175 + background-color: #CCC;
  176 +}
  177 +div.entry-hidden {
  178 + background-color: #CCC;
  179 + color: #333;
  180 +}
  181 +fieldset, .field {
  182 + -moz-border-radius: 5px;
  183 + -webkit-border-radius: 5px;
  184 + border: 1px solid #000;
  185 + margin: 10px auto 10px auto;
  186 + padding: 10px;
  187 + width: 650px;
  188 +}
  189 +#manage-page-widgets fieldset,
  190 +.optional-text-widget { margin-left: 0px; margin-right: 0px; }
  191 +input.url {
  192 + width: 600px;
  193 +}
  194 +
  195 +.user_streams li { line-height: 2.2em; }
  196 +
  197 +.button {
  198 + background-color: #DDD;
  199 + color: #000;
  200 + border: solid 1px grey;
  201 + padding: 5px 10px;
  202 + -moz-border-radius: 15px;
  203 + border-radius: 15px;
  204 +}
  205 +
  206 +
  207 +
  208 +
  209 +.callout {
  210 + line-height: 1.2;
  211 + margin-left: 10px;
  212 +}
  213 +.add-stream-panel { width: 170px; }
  214 +.creating { display: none; }
  215 +.stream-delete-panel { margin-top: 2em; }
  216 +a.stream-delete {
  217 + background-color:#E62020;
  218 + color:white;
  219 + float:right;
  220 + font-weight:bold;
  221 +}
  222 +#release-footer {
  223 + clear: both;
  224 + padding-left: 1em;
  225 +}
  226 +
  227 +
  228 +
  229 +
145 static/css/general-site-kitchen-sink.css
... ... @@ -0,0 +1,145 @@
  1 +/* TODO break up into chunks and @import from general-site.css */
  2 +code {
  3 + font-family: "Courier New", Courier, Arial, monospace;
  4 +}
  5 +body, p, div, span {
  6 + font-family: verdana;
  7 + font-size: 12pt;
  8 + line-height: 1.5;
  9 +}
  10 +h1.logo {
  11 + font-size: 300%;
  12 + line-height: 1;
  13 +}
  14 +h1.logo, h1.logo a {
  15 + color: #333;
  16 + text-decoration: none;
  17 +}
  18 +h1.logo code {
  19 + color: green;
  20 +}
  21 +.tagline {
  22 + font-size: 110%;
  23 + font-style: italic;
  24 + line-height: 1;
  25 + margin-top: 0px;
  26 + padding-top: 0px;
  27 +}
  28 +#content {
  29 + text-align: center;
  30 + min-height: 600px;
  31 + clear: both;
  32 +}
  33 +/* confirm profile */
  34 +.copy, .login, #confirm_profile, #delete_profile {
  35 + margin: 0 auto;
  36 + width: 1090px;
  37 + padding-top: 1em;
  38 +}
  39 +.note {
  40 + font-size: 80%;
  41 +}
  42 +.cancel-link {
  43 + font-size: 120%;
  44 + font-weight: bold;
  45 + margin-top: 3em;
  46 +}
  47 +/* homepage */
  48 +.homepage .logo {
  49 + padding-top: 1em;
  50 +}
  51 +.homepage .tagline {
  52 + margin-bottom: 1em;
  53 +}
  54 +#call-to-action {
  55 + float: left;
  56 + /* margin-left: 300px; */
  57 + text-align: left;
  58 + width: 400px;
  59 + background-color: #DDD;
  60 + border: solid 1px: #666;
  61 + -moz-border-radius: 15px;
  62 + -webkit-border-radius: 15px;
  63 + margin-bottom: 1em;
  64 + padding: 0.5em 1em;
  65 +}
  66 +#call-to-action li, #learn-more-sidebar li {
  67 + list-style: circle outside none;
  68 + margin-left: 2em;
  69 +}
  70 +#learn-more-sidebar {
  71 + border: solid 1px #333;
  72 + float: left;
  73 + text-align: left;
  74 + width: 640px; /* matches video */
  75 + margin-left: 1em;
  76 +}
  77 +
  78 +/* admin and other app specific styles */
  79 +.login {
  80 + text-align: left;
  81 +}
  82 +/* openid login */
  83 +#fopenid {
  84 + width: 600px;
  85 + margin-bottom: 1em;
  86 +}
  87 +#fopenid fieldset {
  88 + border: solid 1px #333;
  89 + -moz-border-radius: 15px;
  90 + -webkit-border-radius: 15px;
  91 +}
  92 +#confirm_profile, #delete_profile {
  93 + width: 600px;
  94 + text-align: left;
  95 +}
  96 +label{
  97 + line-height: 1.5;
  98 +}
  99 +fieldset.required {