diff options
author | Cédric Bonhomme <cedric@cedricbonhomme.org> | 2017-05-23 15:37:50 +0200 |
---|---|---|
committer | Cédric Bonhomme <cedric@cedricbonhomme.org> | 2017-05-23 15:37:50 +0200 |
commit | a756a3e9da58df6247e3437be4c13da25dab1aa0 (patch) | |
tree | 60281271606a5cc6b718d65d998c2d97b3fa4c50 /src | |
parent | Added UTF-8 version of the logo. (diff) | |
parent | Update tags of bookmarks. (diff) | |
download | newspipe-a756a3e9da58df6247e3437be4c13da25dab1aa0.tar.gz newspipe-a756a3e9da58df6247e3437be4c13da25dab1aa0.tar.bz2 newspipe-a756a3e9da58df6247e3437be4c13da25dab1aa0.zip |
Fixed conflicts.
Diffstat (limited to 'src')
-rw-r--r-- | src/web/controllers/__init__.py | 5 | ||||
-rw-r--r-- | src/web/controllers/abstract.py | 1 | ||||
-rw-r--r-- | src/web/controllers/bookmark.py | 29 | ||||
-rw-r--r-- | src/web/controllers/tag.py | 19 | ||||
-rw-r--r-- | src/web/models/bookmark.py | 68 | ||||
-rw-r--r-- | src/web/models/tag.py | 31 | ||||
-rw-r--r-- | src/web/templates/bookmarks.html | 2 | ||||
-rw-r--r-- | src/web/views/bookmark.py | 80 |
8 files changed, 224 insertions, 11 deletions
diff --git a/src/web/controllers/__init__.py b/src/web/controllers/__init__.py index a1b89ea8..5fbc2619 100644 --- a/src/web/controllers/__init__.py +++ b/src/web/controllers/__init__.py @@ -3,7 +3,10 @@ from .category import CategoryController from .article import ArticleController from .user import UserController from .icon import IconController +from .bookmark import BookmarkController +from .tag import BookmarkTagController __all__ = ['FeedController', 'CategoryController', 'ArticleController', - 'UserController', 'IconController'] + 'UserController', 'IconController', 'BookmarkController', + 'BookmarkTagController'] diff --git a/src/web/controllers/abstract.py b/src/web/controllers/abstract.py index 074ce24c..8563d5f2 100644 --- a/src/web/controllers/abstract.py +++ b/src/web/controllers/abstract.py @@ -100,7 +100,6 @@ class AbstractController: def update(self, filters, attrs, return_objs=False, commit=True): assert attrs, "attributes to update must not be empty" - print(attrs) result = self._get(**filters).update(attrs, synchronize_session=False) if commit: db.session.flush() diff --git a/src/web/controllers/bookmark.py b/src/web/controllers/bookmark.py new file mode 100644 index 00000000..c8423414 --- /dev/null +++ b/src/web/controllers/bookmark.py @@ -0,0 +1,29 @@ +import logging +import itertools +from datetime import datetime, timedelta + +from bootstrap import db +from web.models import Bookmark +from .abstract import AbstractController +from .tag import BookmarkTagController + +logger = logging.getLogger(__name__) + + +class BookmarkController(AbstractController): + _db_cls = Bookmark + + def count_by_href(self, **filters): + return self._count_by(Bookmark.href, filters) + + def update(self, filters, attrs): + BookmarkTagController(self.user_id) \ + .read(**{'bookmark_id': filters["id"]}) \ + .delete() + + for tag in attrs['tags']: + BookmarkTagController(self.user_id) \ + .update({'id': tag.id}, {'bookmark_id': filters["id"]}) + + del attrs['tags'] + return super().update(filters, attrs) diff --git a/src/web/controllers/tag.py b/src/web/controllers/tag.py new file mode 100644 index 00000000..a40387c9 --- /dev/null +++ b/src/web/controllers/tag.py @@ -0,0 +1,19 @@ +import logging +import itertools +from datetime import datetime, timedelta + +from bootstrap import db +from .abstract import AbstractController +from web.models.tag import BookmarkTag + +logger = logging.getLogger(__name__) + + +class BookmarkTagController(AbstractController): + _db_cls = BookmarkTag + + def count_by_href(self, **filters): + return self._count_by(BookmarkTag.text, filters) + + def update(self, filters, attrs): + return super().update(filters, attrs) diff --git a/src/web/models/bookmark.py b/src/web/models/bookmark.py new file mode 100644 index 00000000..6eee3cba --- /dev/null +++ b/src/web/models/bookmark.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# Newspipe - A Web based news aggregator. +# Copyright (C) 2010-2016 Cédric Bonhomme - https://www.cedricbonhomme.org +# +# For more information : https://github.com/newspipe/newspipe +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +__author__ = "Cedric Bonhomme" +__version__ = "$Revision: 0.1 $" +__date__ = "$Date: 2016/12/07 $" +__revision__ = "$Date: 2016/12/07 $" +__copyright__ = "Copyright (c) Cedric Bonhomme" +__license__ = "GPLv3" + +from bootstrap import db +from datetime import datetime +from sqlalchemy import desc +from sqlalchemy.orm import validates +from sqlalchemy.ext.associationproxy import association_proxy + +from web.models.tag import BookmarkTag +from web.models.right_mixin import RightMixin + + +class Bookmark(db.Model, RightMixin): + """ + Represent a bookmark. + """ + id = db.Column(db.Integer(), primary_key=True) + href = db.Column(db.String(), default="") + title = db.Column(db.String(), default="") + description = db.Column(db.String(), default="FR") + shared = db.Column(db.Boolean(), default=False) + to_read = db.Column(db.Boolean(), default=False) + time = db.Column(db.DateTime(), default=datetime.utcnow) + user_id = db.Column(db.Integer(), db.ForeignKey('user.id')) + + # relationships + tags = db.relationship(BookmarkTag, backref='of_bookmark', lazy='dynamic', + cascade='all,delete-orphan', + order_by=desc(BookmarkTag.text)) + tags_proxy = association_proxy('tags', 'text') + + + @validates('description') + def validates_title(self, key, value): + return str(value).strip() + + @validates('extended') + def validates_description(self, key, value): + return str(value).strip() + + def __repr__(self): + return '<Bookmark %r>' % (self.href) diff --git a/src/web/models/tag.py b/src/web/models/tag.py index 8d7fe4d4..ab901cda 100644 --- a/src/web/models/tag.py +++ b/src/web/models/tag.py @@ -1,22 +1,37 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -from sqlalchemy import Column, ForeignKey, Integer, String -from sqlalchemy.orm import relationship - from bootstrap import db -class Tag(db.Model): - text = Column(String, primary_key=True, unique=False) +class ArticleTag(db.Model): + text = db.Column(db.String, primary_key=True, unique=False) + # user_id = db.Column(db.Integer(), db.ForeignKey('user.id')) # foreign keys - article_id = Column(Integer, ForeignKey('article.id', ondelete='CASCADE'), + article_id = db.Column(db.Integer, db.ForeignKey('article.id', ondelete='CASCADE'), primary_key=True) # relationships - article = relationship('Article', back_populates='tag_objs', - foreign_keys=[article_id]) + article = db.relationship('Article', back_populates='tag_objs', + foreign_keys=[article_id]) def __init__(self, text): self.text = text + + +class BookmarkTag(db.Model): + id = db.Column(db.Integer, primary_key=True) + text = db.Column(db.String, unique=False) + + # foreign keys + user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + bookmark_id = db.Column(db.Integer, db.ForeignKey('bookmark.id', ondelete='CASCADE')) + + # relationships + bookmark = db.relationship('Bookmark', back_populates='tags', + cascade="all,delete", foreign_keys=[bookmark_id]) + + # def __init__(self, text, user_id): + # self.text = text + # self.user_id = user_id diff --git a/src/web/templates/bookmarks.html b/src/web/templates/bookmarks.html index fc0e3aaa..3e65d2c0 100644 --- a/src/web/templates/bookmarks.html +++ b/src/web/templates/bookmarks.html @@ -6,7 +6,7 @@ {% for bookmark in bookmarks %} <li class="list-group-item"> <a href="{{ bookmark.href }}">{{ bookmark.href }}</a> - <a href="{{ bookmark.href }}">{{ bookmark.tags }}</a> + <a href="{{ bookmark.href }}">{{ bookmark.tags_proxy }}</a> <a href="{{ url_for('bookmark.form', bookmark_id=bookmark.id) }}">edit</a> </li> {% endfor %} diff --git a/src/web/views/bookmark.py b/src/web/views/bookmark.py new file mode 100644 index 00000000..64acded4 --- /dev/null +++ b/src/web/views/bookmark.py @@ -0,0 +1,80 @@ +import logging +from werkzeug.exceptions import BadRequest + +from flask import Blueprint, render_template, flash, \ + redirect, request, url_for +from flask_babel import gettext +from flask_login import login_required, current_user + +import conf +from bootstrap import db +from web.forms import BookmarkForm +from web.controllers import BookmarkController, BookmarkTagController + +logger = logging.getLogger(__name__) +bookmarks_bp = Blueprint('bookmarks', __name__, url_prefix='/bookmarks') +bookmark_bp = Blueprint('bookmark', __name__, url_prefix='/bookmark') + + +@bookmarks_bp.route('/', methods=['GET']) +@login_required +def list(): + "Lists the bookmarks." + bookmark_contr = BookmarkController(current_user.id) + return render_template('bookmarks.html', + bookmarks=BookmarkController(current_user.id).read().order_by('time')) + + +@bookmark_bp.route('/create', methods=['GET']) +@bookmark_bp.route('/edit/<int:bookmark_id>', methods=['GET']) +@login_required +def form(bookmark_id=None): + action = gettext("Add a bookmark") + head_titles = [action] + if bookmark_id is None: + return render_template('edit_bookmark.html', action=action, + head_titles=head_titles, form=BookmarkForm()) + bookmark = BookmarkController(current_user.id).get(id=bookmark_id) + action = gettext('Edit bookmark') + head_titles = [action] + form = BookmarkForm(obj=bookmark) + form.tags.data = bookmark.tags_proxy + return render_template('edit_bookmark.html', action=action, + head_titles=head_titles, bookmark=bookmark, + form=form) + + +@bookmark_bp.route('/create', methods=['POST']) +@bookmark_bp.route('/edit/<int:bookmark_id>', methods=['POST']) +@login_required +def process_form(bookmark_id=None): + form = BookmarkForm() + bookmark_contr = BookmarkController(current_user.id) + tag_contr = BookmarkTagController(current_user.id) + + if not form.validate(): + return render_template('edit_bookmark.html', form=form) + + tags = [] + for tag in form.tags.data.split(','): + new_tag = tag_contr.create(text= tag.strip(), user_id= current_user.id) + tags.append(new_tag) + + bookmark_attr = {'href': form.href.data, + 'description': form.description.data, + 'title': form.title.data, + 'tags': tags, + 'shared': form.shared.data, + 'to_read': form.to_read.data} + + if bookmark_id is not None: + bookmark_contr.update({'id': bookmark_id}, bookmark_attr) + flash(gettext('Bookmark successfully updated.'), 'success') + return redirect(url_for('bookmark.form', bookmark_id=bookmark_id)) + + # Create a new bookmark + new_bookmark = bookmark_contr.create(**bookmark_attr) + + flash(gettext('Bookmark successfully created.'), 'success') + + return redirect(url_for('bookmark.form', bookmark_id=new_bookmark.id)) |