Example #1
0
def edit():
    """
    POST /comic/edit/:id

    Updates comic details.
    """

    comic = get_or_404(db.comic, request.args(0))

    # Ensure the user owns this comic
    if not comic_helpers.user_can_edit(db, comic.id, auth.user.id):
        flash_and_redirect_back('danger', 'You cannot edit a comic you did not create.')

    form = ComicForm(comic)

    if form.process().accepted:
        flash('info', 'Comic updated successfully.', comic.url)
    elif form.form.errors:
        flash('danger', 'Form has errors.')

    return {
        'form': form.form,
        'comic': comic,
        'owner': auth.user,
    }
Example #2
0
def delete():
    """
    POST /box/delete/:id

    Deletes a box and ensures any comics that were in only this box are moved to 'Unfiled'.
    """

    box = get_or_404(db.box, request.args(0), owner=auth.user.id)

    if box.is_unfiled:
        flash('danger', 'You cannot delete the Unfiled box.', box.url)

    comics = [x.comic for x in box.comicbox.select()]

    # Find the comics who only reside in the box we're deleting
    count = db.comicbox.id.count()
    comic_just_in_box = db(db.comicbox.comic.belongs(comics)).select(db.comicbox.id, count, groupby=db.comicbox.comic)
    comic_just_in_box = filter(lambda row: row[count] == 1, comic_just_in_box)

    # Move all comics that only reside in the box we're deleting to 'Unfiled'
    for record in comic_just_in_box:
        record.comicbox.update_record(box=_unfiled_box().id)

    # Remove all comics from this box
    db(db.comicbox.box == box.id).delete()

    # Delete the old box
    box.delete_record()

    flash('info', '%s box deleted.' % box.name, URL('collection', 'view', args=[auth.user.id]))
Example #3
0
def search():
    """
    GET /comic/search?search=:query

    Searches all public comics across a number of criteria.
    """

    original_search = request.get_vars.get('search', '')

    user_id = auth.user.id if auth.is_logged_in() else 0

    # generate a base query which finds all comics that the logged in user has permission to see
    base_query = db(db.comic.id == db.comicbox.comic)(db.comicbox.box == db.box.id)(
        (db.box.private == False) | (db.box.owner == user_id))

    # basic partial matching
    fuzzy_like = lambda f, q: f.like('%{0}%'.format(q))

    # generate the queries for each criteria
    queries = {
        'title': lambda q: base_query(fuzzy_like(db.comic.title, q)),
        'publisher': lambda q: base_query(db.publisher.id == db.comic.publisher)(fuzzy_like(db.publisher.name, q)),
        'writer': lambda q: base_query(db.comicwriter.comic == db.comic.id)(db.writer.id == db.comicwriter.writer)(
            fuzzy_like(db.writer.name, q)),
        'artist': lambda q: base_query(db.comicartist.comic == db.comic.id)(db.artist.id == db.comicartist.artist)(
            fuzzy_like(db.artist.name, q)),
    }

    only_field, search = None, original_search

    search_parts = original_search.split(':', 1)

    # determine which (if any) criteria to search against
    if len(search_parts) > 1:
        if search_parts[0] in queries:
            only_field, search = search_parts
        else:
            flash('danger', 'Invalid criteria "%s", expected one of: %s' % (search_parts[0], ', '.join(queries.keys())))

    if only_field:
        # filter using a single criteria
        comics = queries[only_field](search).select(db.comic.ALL, distinct=True)
    else:
        # combine all queries to a single set of comics
        query_results = map(lambda q: q(search).select(db.comic.ALL, distinct=True), queries.values())
        comics = reduce(lambda c, q: c | q, query_results)

    return {
        'original_search': original_search,
        'search': search,
        'comics': comics,
        'only_field': only_field
    }
Example #4
0
def create():
    """
    POST /box/create

    Creates a new box for this user.
    """

    form = SQLFORM(db.box, fields=['name', 'private'])
    add_element_required_attr(db.box, form)

    form.vars.owner = auth.user

    if form.process(onvalidation=_validate_box_form).accepted:
        flash('success', 'Created box.', URL('box', 'view', args=[form.vars.id]))
    elif form.errors:
        flash('danger', 'Form has errors.')

    return {
        'form': form
    }
Example #5
0
def view():
    """
    GET /box/view/:id

    Views a box, ensures that the logged in user has permission to view it.
    """

    user_id = auth.user.id if auth.is_logged_in() else 0
    box = get_or_404(db.box, ((db.box.id == request.args(0)) & ((db.box.owner == user_id) | (db.box.private == False))))

    # find all comics in this box
    comics = db(db.comicbox.comic == db.comic.id)(db.comicbox.box == box.id).select(db.comic.ALL)
    comic_ids = map(lambda c: c.id, comics)

    # find all the comics owned by this user that aren't already in the box
    other_comics = db(db.comic.id == db.comicbox.comic)(db.box.id == db.comicbox.box)(
        db.box.owner == user_id).select(db.comic.ALL, groupby=db.comic.id)
    other_comics = filter(lambda c: c.id not in comic_ids, other_comics)

    user_owned = user_id == box.owner.id
    can_edit = user_owned and not box.is_unfiled

    if can_edit:
        rename_form = SQLFORM(db.box, box, fields=['name'], showid=False)
        add_element_required_attr(db.box, rename_form)

        if rename_form.process(onvalidation=_validate_box_form).accepted:
            flash('info', 'Box renamed successfully.', request.env['PATH_INFO'])
        elif rename_form.errors:
            flash('danger', 'Form has errors.')
    else:
        rename_form = None

    return {
        'box': box,
        'comics': comics,
        'other_comics': other_comics,
        'can_edit': can_edit,
        'user_owned': user_owned,
        'rename_form': rename_form
    }
Example #6
0
def create():
    """
    POST /comic/create?box=:box_id

    Creates a new comic.
    """

    form = ComicForm()

    # Pre-select the box that the user wants to add to
    if not form.form.vars.box and request.get_vars['box']:
        form.form.vars.box = get_or_404(db.box, request.get_vars['box'], owner=auth.user.id).id

    if form.process().accepted:
        flash('success', 'Created comic.', URL('comic', 'view', args=[form.id]))
    elif form.form.errors:
        flash('danger', 'Form has errors.')

    return {
        'form': form.form,
        'owner': auth.user,
    }
Example #7
0
def add_comic():
    """
    POST /box/add_comic

    Adds a comic to a box, also may create or update an existing box if 'new box' was specified.
    The 'comic' POST var can occur multiple times to add many comics to a single box in one operation.
    """

    # Create a new box
    if request.post_vars['box'] == 'new':
        target_box = db.box(db.box.name.like(request.post_vars['name']) & (db.box.owner == auth.user.id))
        private = bool(request.post_vars['private'])

        if target_box:
            target_box.update(private=private)
        else:
            target_box_id = db.box.insert(name=request.post_vars['name'], owner=auth.user.id, private=private)
            target_box = db.box[target_box_id]
    else:
        target_box = get_or_404(db.box, request.post_vars['box'], owner=auth.user.id)

    raw_comic = request.post_vars['comic']

    if raw_comic is None:
        flash_and_redirect_back('warning', 'No comics selected.')

    comics = raw_comic if isinstance(raw_comic, list) else [raw_comic]

    for source_comic_id in comics:
        source_comic = get_or_404(db.comic, source_comic_id)

        # Is the comic already in the box we want to add it to?
        if db.comicbox((db.comicbox.box == target_box.id) & (db.comicbox.comic == source_comic.id)):
            flash_and_redirect_back('warning', 'This comic already exists in %s.' % target_box.name)

        # If this user doesn't own the comic, duplicate it
        if db(db.box.owner == auth.user.id)(db.comicbox.box == db.box.id)(db.comicbox.comic == source_comic.id).isempty():
            target_comic_id = db.comic.insert(
                publisher=source_comic.publisher,
                title=source_comic.title,
                issue=source_comic.issue,
                description=source_comic.description,
                cover_image=source_comic.cover_image
            )

            for comicwriter in source_comic.comicwriter.select():
                db.comicwriter.insert(writer=comicwriter.writer, comic=target_comic_id)

            for comicartist in source_comic.comicartist.select():
                db.comicartist.insert(artist=comicartist.artist, comic=target_comic_id)

        elif target_box.is_unfiled:
            return flash_and_redirect_back('danger',
                                           'This comic cannot be added to "Unfiled" as it is already belongs to a box.')

        else:
            target_comic_id = source_comic.id

        # Add comic to box
        db.comicbox.insert(comic=target_comic_id, box=target_box.id)

        # Find the Unfiled box for this user
        if not target_box.is_unfiled:
            db((db.comicbox.comic == target_comic_id) & (db.comicbox.box == _unfiled_box().id)).delete()

    flash_text = 'Added comic%s to %s.' % ('s' if len(comics) > 1 else '', target_box.name)

    # if we just duplicated this comic, redirect to the new comic
    if source_comic.owner.id != auth.user.id:
        flash('success', flash_text, URL('comic', 'view', args=[target_comic_id]))

    # otherwise, redirect back
    else:
        flash_and_redirect_back('success', flash_text)