diff --git a/apps/opml_import/views.py b/apps/opml_import/views.py index e98dead4c..b466503af 100644 --- a/apps/opml_import/views.py +++ b/apps/opml_import/views.py @@ -37,21 +37,9 @@ def opml_import(xml_opml, user): print '\t%s' % (feed.title,) feed_data = dict(feed_address=feed.xmlUrl, feed_link=feed.htmlUrl, feed_title=feed.title) feeds.append(feed_data) - new_feed = Feed(**feed_data) - try: - new_feed.save() - except IntegrityError: - new_feed = Feed.objects.get(feed_address=feed.xmlUrl) - us = UserSubscription(feed=new_feed, user=user) - try: - us.save() - except IntegrityError: - us = UserSubscription.objects.get(feed=new_feed, user=user) - user_sub_folder = UserSubscriptionFolders(user=user, feed=new_feed, user_sub=us, folder=folder.text) - try: - user_sub_folder.save() - except IntegrityError: - print 'Can\'t save user_sub_folder' + new_feed, _ = Feed.objects.get_or_create(feed_address=feed.xmlUrl, defaults=feed_data) + us, _ = UserSubscription.objects.get_or_create(feed=new_feed, user=user) + user_sub_folder, _ = UserSubscriptionFolders.objects.get_or_create(user=user, feed=new_feed, user_sub=us, defaults=dict(folder=folder.text)) data = json_encode(dict(message=message, code=code, payload=dict(feeds=feeds, feed_count=len(feeds)))) cache.delete('usersub:%s' % user) diff --git a/media/css/reader.css b/media/css/reader.css index 2283534fe..871d0058b 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -85,7 +85,8 @@ a img { display: none; } -.NB-login label { +.NB-login label, +.NB-login .NB-login-label { margin-top: 2px; color:#90A0B0; font-size:13px; @@ -93,6 +94,25 @@ a img { /* text-transform: uppercase;*/ } +.NB-login .NB-login-label { + font-weight: bold; +} + +.NB-login .NB-login-text { + font-size: 13px; + color: #90A0B0; + margin-bottom: 30px; +} + +.NB-login .NB-login-text a { + text-decoration: none; + color: #3E4773; +} + +.NB-login .NB-login-text a:hover { + color: #0E1763; +} + /* ============= */ /* = Feed List = */ /* ============= */ @@ -774,16 +794,68 @@ form.opml_import_form input { /* = Classifier = */ /* ============== */ -.NB-classifier { +.NB-modal { padding: 12px; } -.NB-classifier h2 { +.NB-modal h2 { margin: 0; padding: 0; font-size: 130%; } +.NB-modal h5 { + border-bottom: 1px solid #A0A0A0; + padding: 16px 0 0px; + margin: 0 0 6px 0; + color: #808080; + text-transform: uppercase; + font-weight: normal; + font-size: 70%; +} + +.NB-modal .NB-modal-field { + margin: 0 0 0 24px; + position: relative; + clear: both; +} + +.NB-modal .NB-modal-field input[type=text] { + width: 446px; + font-size: 14px; +} + +.NB-modal .NB-modal-field input[type=checkbox] { + margin: 4px 0 0 -20px; + float: left; +} + +.NB-modal .NB-modal-title { + font-weight: bold; +} + +.NB-disabled { + color: #A0A0A0; +} + +.NB-modal .NB-modal-submit { + margin: 16px 0 0 0; + font-size: 13px; +} + +.NB-modal .NB-modal-submit input[type=submit] { + font-size: 14px; +} + +.NB-modal img.feed_favicon { + margin: 0 6px 0 0; + vertical-align: middle; +} + +/* ============== */ +/* = Classifier = */ +/* ============== */ + .NB-classifier h2.NB-like { color: #007000; } @@ -791,59 +863,10 @@ form.opml_import_form input { .NB-classifier h2.NB-dislike { color: #700000; } - -.NB-classifier h5 { - border-bottom: 1px solid #A0A0A0; - padding: 16px 0 0px; - margin: 0 0 6px -24px; - color: #808080; - text-transform: uppercase; - font-weight: normal; - font-size: 70%; -} - -.NB-classifier .NB-classifier-field { - margin: 0 0 0 24px; - position: relative; - clear: both; -} - -.NB-classifier .NB-classifier-field input[type=text] { - width: 446px; - font-size: 14px; -} - -.NB-classifier .NB-classifier-field input[type=checkbox] { - margin: 4px 0 0 -20px; - float: left; -} - -.NB-classifier .NB-classifier-title { - font-weight: bold; -} - .NB-classifier .NB-classifier-facet-disabled { color: #A0A0A0; } -.NB-disabled { - color: #A0A0A0; -} - -.NB-classifier .NB-classifier-submit { - margin: 16px 0 0 0; - font-size: 13px; -} - -.NB-classifier .NB-classifier-submit input[type=submit] { - font-size: 14px; -} - -.NB-classifier img.feed_favicon { - margin: 0 6px 0 0; - vertical-align: middle; -} - .NB-classifier-title-display { margin: 6px 0 0 0; } diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index f98bbeaab..0e7c2de41 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -1,6 +1,6 @@ (function($) { - NEWSBLUR.reader = function() { + NEWSBLUR.Reader = function() { var self = this; this.$feed_list = $('#feed_list'); this.$story_titles = $('#story_titles'); @@ -35,11 +35,11 @@ this.apply_resizable_layout(); this.cornerize_buttons(); this.handle_keystrokes(); - this.setup_taskbar_nav_left(); + // this.setup_taskbar_nav_left(); this.setup_feed_page_iframe_load(); }; - NEWSBLUR.reader.prototype = { + NEWSBLUR.Reader.prototype = { // ================= // = Node Creation = @@ -1190,10 +1190,10 @@ // = Taskbar = // =========== - $.targetIs(e, { tagSelector: '.task_button_menu' }, function($t, $p){ + $.targetIs(e, { tagSelector: '.NB-task-add' }, function($t, $p){ e.preventDefault(); - self.open_taskbar_menu($t); - }); + self.open_add_modal(); + }); $.targetIs(e, { tagSelector: '.task_button_view' }, function($t, $p){ e.preventDefault(); self.switch_taskbar_view($t); @@ -1201,12 +1201,7 @@ $.targetIs(e, { tagSelector: '.task_return', childOf: '.NB-taskbar' }, function($t, $p){ e.preventDefault(); self.show_feed_page_contents(); - }); - $.targetIs(e, { tagSelector: '.NB-task-import-upload-opml' }, function($t, $p){ - e.preventDefault(); - self.open_opml_import_modal_form($t); - }); - + }); }, @@ -1284,7 +1279,13 @@ // =================== // = Bottom Task Bar = // =================== - + + open_add_modal: function() { + var feed_id = this.active_feed; + + NEWSBLUR.add_feed = new NEWSBLUR.ReaderAddFeed(); + }, + setup_taskbar_nav_left: function() { var self = this; var $task_buttons = $('.NB-taskbar .taskbar_nav_left .task_button'); @@ -1361,7 +1362,7 @@ $(document).ready(function() { - var _Reader = new NEWSBLUR.reader(); + NEWSBLUR.reader = new NEWSBLUR.Reader(); }); \ No newline at end of file diff --git a/media/js/newsblur/reader_add_feed.js b/media/js/newsblur/reader_add_feed.js new file mode 100644 index 000000000..502ecd245 --- /dev/null +++ b/media/js/newsblur/reader_add_feed.js @@ -0,0 +1,161 @@ +NEWSBLUR.ReaderAddFeed = function(feed_id, score, options) { + var defaults = {}; + + this.options = $.extend({}, defaults, options); + this.model = NEWSBLUR.AssetModel.reader(); + this.google_favicon_url = 'http://www.google.com/s2/favicons?domain_url='; + this.runner(); +}; + +NEWSBLUR.ReaderAddFeed.prototype = { + + runner: function() { + this.make_modal(); + this.handle_cancel(); + this.open_modal(); + }, + + make_modal: function() { + var self = this; + + this.$add = $.make('div', { className: 'NB-add NB-modal' }, [ + $.make('h2', { className: 'NB-modal-title' }, 'Add a feed'), + $.make('form', { method: 'post', enctype: 'multipart/form-data', className: 'NB-add-form' }, [ + $.make('div', { className: 'NB-add-field' }, [ + $.make('h5', 'Search for a publisher'), + $.make('h5', 'Import from Google Reader'), + $.make('h5', 'Upload OPML (from Google Reader)'), + $.make('input', { type: 'file', name: 'file', id: 'opml_file_input' }), + $.make('input', { type: 'submit', className: 'NB-add-opml-button', value: 'Upload OPML File' }).click(function(e) { + e.preventDefault(); + self.handle_opml_upload(); + return false; + }) + ]), + $.make('div', { className: 'NB-modal-submit' }, [ + $.make('input', { name: 'score', value: this.score, type: 'hidden' }), + $.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }), + $.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }), + $.make('input', { type: 'submit', disabled: 'true', className: 'NB-disabled', value: 'Check what you like above...' }), + ' or ', + $.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel') + ]) + ]).bind('submit', function(e) { + e.preventDefault(); + self.save(); + return false; + }) + ]); + + }, + + open_modal: function() { + var self = this; + + var $holder = $.make('div', { className: 'NB-modal-holder' }).append(this.$add).appendTo('body').css({'visibility': 'hidden', 'display': 'block', 'width': 600}); + var height = $('.NB-add', $holder).outerHeight(true); + $holder.css({'visibility': 'visible', 'display': 'none'}); + + this.$add.modal({ + 'minWidth': 600, + 'minHeight': height, + 'overlayClose': true, + 'onOpen': function (dialog) { + dialog.overlay.fadeIn(200, function () { + dialog.container.fadeIn(200); + dialog.data.fadeIn(200); + }); + }, + 'onShow': function(dialog) { + $('#simplemodal-container').corners('6px').css({'width': 600, 'height': height}); + // $('.NB-classifier-tag', self.$add).corners('4px'); + }, + 'onClose': function(dialog) { + dialog.data.hide().empty().remove(); + dialog.container.hide().empty().remove(); + dialog.overlay.fadeOut(200, function() { + dialog.overlay.empty().remove(); + $.modal.close(); + }); + $('.NB-modal-holder').empty().remove(); + } + }); + }, + + handle_cancel: function() { + var $cancel = $('.NB-modal-cancel', this.$add); + + $cancel.click(function(e) { + e.preventDefault(); + $.modal.close(); + }); + }, + + serialize_classifier: function() { + var data = $('.NB-add form input').serialize(); + + return data; + }, + + save: function() { + var $save = $('.NB-modal input[type=submit]'); + var story_id = this.story_id; + var data = this.serialize_classifier(); + + $save.text('Saving...').addClass('NB-disabled').attr('disabled', true); + this.model.save_classifier_publisher(data, function() { + $.modal.close(); + }); + }, + + // ======== + // = OPML = + // ======== + + handle_opml_upload: function() { + var self = this; + + // NEWSBLUR.log(['Uploading']); + $.ajaxFileUpload({ + url: '/opml/opml_upload', + secureuri: false, + fileElementId: 'opml_file_input', + dataType: 'json', + success: function (data, status) + { + if (typeof data.code != 'undefined') { + if (data.code <= 0) { + // NEWSBLUR.log(['Success - Error', data.code]); + } else { + // NEWSBLUR.log(['Success', data]); + NEWSBLUR.reader.load_feeds(); + } + } + }, + error: function (data, status, e) + { + NEWSBLUR.log(['Error', data, status, e]); + } + }); + + return false; + }, + + handle_opml_form: function() { + var self = this; + var $form = $('form.opml_import_form'); + + // NEWSBLUR.log(['OPML Form:', $form]); + + var callback = function(e) { + // NEWSBLUR.log(['OPML Callback', e]); + }; + + $form.submit(function() { + + self.model.process_opml_import($form.serialize(), callback); + return false; + }); + }, + +}; \ No newline at end of file diff --git a/media/js/newsblur/reader_classifier.js b/media/js/newsblur/reader_classifier.js index 05a8ecc65..77ad104df 100644 --- a/media/js/newsblur/reader_classifier.js +++ b/media/js/newsblur/reader_classifier.js @@ -91,18 +91,18 @@ var classifier = { } } - this.$classifier = $.make('div', { className: 'NB-classifier' }, [ - $.make('h2', { className: 'NB-classifier-modal-title' }), + this.$classifier = $.make('div', { className: 'NB-classifier NB-modal' }, [ + $.make('h2', { className: 'NB-modal-title' }), $.make('form', { method: 'post', className: 'NB-publisher' }, [ - ($feed_authors.length && $.make('div', { className: 'NB-classifier-field' }, [ + ($feed_authors.length && $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Authors'), $.make('div', { className: 'NB-classifier-authors' }, $feed_authors) ])), - ($feed_tags.length && $.make('div', { className: 'NB-classifier-field' }, [ + ($feed_tags.length && $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Categories & Tags'), $.make('div', { className: 'NB-classifier-tags' }, $feed_tags) ])), - $.make('div', { className: 'NB-classifier-field' }, [ + $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Everything by This Publisher'), $.make('input', { type: 'checkbox', name: 'facet', value: 'publisher', id: 'classifier_publisher' }), $.make('label', { 'for': 'classifier_publisher' }, [ @@ -110,13 +110,13 @@ var classifier = { $.make('span', { className: 'feed_title' }, feed.feed_title) ]) ]), - $.make('div', { className: 'NB-classifier-submit' }, [ + $.make('div', { className: 'NB-modal-submit' }, [ $.make('input', { name: 'score', value: this.score, type: 'hidden' }), $.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }), $.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }), $.make('input', { type: 'submit', disabled: 'true', className: 'NB-disabled', value: 'Check what you like above...' }), ' or ', - $.make('a', { href: '#', className: 'NB-classifier-cancel' }, 'cancel') + $.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel') ]) ]).bind('submit', function(e) { e.preventDefault(); @@ -125,7 +125,7 @@ var classifier = { }) ]); - var $modal_title = $('.NB-classifier-modal-title', this.$classifier); + var $modal_title = $('.NB-modal-title', this.$classifier); if (this.score == 1) { $modal_title.html('What do you like about this publisher?'); } else if (this.score == -1) { @@ -155,10 +155,10 @@ var classifier = { $story_tags.push($tag); } - this.$classifier = $.make('div', { className: 'NB-classifier' }, [ - $.make('h2', { className: 'NB-classifier-modal-title' }), + this.$classifier = $.make('div', { className: 'NB-classifier NB-modal' }, [ + $.make('h2', { className: 'NB-modal-title' }), $.make('form', { method: 'post' }, [ - (story.story_title && $.make('div', { className: 'NB-classifier-field' }, [ + (story.story_title && $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Story Title'), $.make('input', { type: 'checkbox', name: 'facet', value: 'title', id: 'classifier_title' }), $.make('input', { type: 'text', value: story.story_title, className: 'NB-classifier-title-highlight' }), @@ -170,18 +170,18 @@ var classifier = { ]) ]) ])), - (story.story_authors && $.make('div', { className: 'NB-classifier-field' }, [ + (story.story_authors && $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Story Author'), $.make('input', { type: 'checkbox', name: 'facet', value: 'author', id: 'classifier_author' }), $.make('label', { 'for': 'classifier_author' }, [ $.make('b', story.story_authors) ]) ])), - ($story_tags.length && $.make('div', { className: 'NB-classifier-field' }, [ + ($story_tags.length && $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Story Categories & Tags'), $.make('div', { className: 'NB-classifier-tags' }, $story_tags) ])), - $.make('div', { className: 'NB-classifier-field' }, [ + $.make('div', { className: 'NB-modal-field' }, [ $.make('h5', 'Everything by This Publisher'), $.make('input', { type: 'checkbox', name: 'facet', value: 'publisher', id: 'classifier_publisher' }), $.make('label', { 'for': 'classifier_publisher' }, [ @@ -189,13 +189,13 @@ var classifier = { $.make('span', { className: 'feed_title' }, feed.feed_title) ]) ]), - $.make('div', { className: 'NB-classifier-submit' }, [ + $.make('div', { className: 'NB-modal-submit' }, [ $.make('input', { name: 'score', value: this.score, type: 'hidden' }), $.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }), $.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }), $.make('input', { type: 'submit', disabled: 'true', className: 'NB-disabled', value: 'Check what you like above...' }), ' or ', - $.make('a', { href: '#', className: 'NB-classifier-cancel' }, 'cancel') + $.make('a', { href: '#', className: 'NB-modal-cancel' }, 'cancel') ]) ]).bind('submit', function(e) { e.preventDefault(); @@ -204,7 +204,7 @@ var classifier = { }) ]); - var $modal_title = $('.NB-classifier-modal-title', this.$classifier); + var $modal_title = $('.NB-modal-title', this.$classifier); if (this.score == 1) { $modal_title.html('What do you like about this story?'); } else if (this.score == -1) { @@ -215,7 +215,7 @@ var classifier = { open_modal: function() { var self = this; - var $holder = $.make('div', { className: 'NB-classifier-holder' }).append(this.$classifier).appendTo('body').css({'visibility': 'hidden', 'display': 'block', 'width': 600}); + var $holder = $.make('div', { className: 'NB-modal-holder' }).append(this.$classifier).appendTo('body').css({'visibility': 'hidden', 'display': 'block', 'width': 600}); var height = $('.NB-classifier', $holder).outerHeight(true); $holder.css({'visibility': 'visible', 'display': 'none'}); @@ -240,7 +240,7 @@ var classifier = { dialog.overlay.empty().remove(); $.modal.close(); }); - $('.NB-classifier-holder').empty().remove(); + $('.NB-modal-holder').empty().remove(); } }); }, @@ -295,7 +295,7 @@ var classifier = { }, handle_cancel: function() { - var $cancel = $('.NB-classifier-cancel', this.$classifier); + var $cancel = $('.NB-modal-cancel', this.$classifier); $cancel.click(function(e) { e.preventDefault(); diff --git a/settings.py b/settings.py index 9b88714b6..21e294ad2 100644 --- a/settings.py +++ b/settings.py @@ -180,6 +180,7 @@ COMPRESS_JS = { 'js/newsblur/assetmodel.js', 'js/newsblur/reader.js', 'js/newsblur/reader_classifier.js', + 'js/newsblur/reader_add_feed.js', ), 'output_filename': 'release/all-compressed-?.js' } diff --git a/templates/reader/feeds.xhtml b/templates/reader/feeds.xhtml index fb96eefc3..30d2e6027 100644 --- a/templates/reader/feeds.xhtml +++ b/templates/reader/feeds.xhtml @@ -7,20 +7,7 @@
@@ -43,7 +30,9 @@ {% if form.errors %}

{{ form.errors }}

{% endif %} - +
Want an account?
+
Talk to @samuelclay.
+
{{ form.username.label_tag }}