Esempio n. 1
0
def _get_scan_table(series):
    # freshly added series have no scans on preview page
    if series is None:
        return None, None

    if not series.is_comics_publication:
        return Cover.objects.none(), get_image_tag(cover=None, 
          zoom_level=ZOOM_MEDIUM, alt_text='First Issue Cover', 
          is_comics_publication=series.is_comics_publication)
    # all a series' covers + all issues with no covers
    covers = Cover.objects.filter(issue__series=series, deleted=False) \
                          .select_related()
    issues = series.issues_without_covers()

    scans = list(issues)
    scans.extend(list(covers))
    scans.sort(key=attrgetter('sort_code'))

    if covers:
        first_image_tag = get_image_tag(cover=covers[0], zoom_level=ZOOM_MEDIUM,
                                        alt_text='First Issue Cover')
    else:
        first_image_tag = None

    return scans, first_image_tag
Esempio n. 2
0
def _get_scan_table(series, show_cover=True):
    # freshly added series have no scans on preview page
    if series is None:
        return None, None, None

    if not series.is_comics_publication:
        return Cover.objects.none(), get_image_tag(cover=None, 
          zoom_level=ZOOM_MEDIUM, alt_text='First Issue Cover', 
          can_have_cover=series.is_comics_publication), None
    # all a series' covers + all issues with no covers
    covers = Cover.objects.filter(issue__series=series, deleted=False) \
                          .select_related()
    issues = series.issues_without_covers()

    list_covers = list(covers)
    scans = list(issues)
    scans.extend(list_covers)
    scans.sort(key=attrgetter('sort_code'))

    if covers and show_cover:
        selected_cover = covers[randint(0, covers.count()-1)]
        image_tag = get_image_tag(cover=selected_cover,
                                  zoom_level=ZOOM_MEDIUM,
                                  alt_text='Random Cover from Series')
        issue = selected_cover.issue
    else:
        image_tag = None
        issue = None

    return scans, image_tag, issue
Esempio n. 3
0
def _get_scan_table(series):
    # freshly added series have no scans on preview page
    if series is None:
        return None, None

    if not series.is_comics_publication:
        return Cover.objects.none(), get_image_tag(
            cover=None,
            zoom_level=ZOOM_MEDIUM,
            alt_text='First Issue Cover',
            is_comics_publication=series.is_comics_publication)
    # all a series' covers + all issues with no covers
    covers = Cover.objects.filter(issue__series=series, deleted=False) \
                          .select_related()
    issues = series.issues_without_covers()

    scans = list(issues)
    scans.extend(list(covers))
    scans.sort(key=attrgetter('sort_code'))

    if covers:
        first_image_tag = get_image_tag(cover=covers[0],
                                        zoom_level=ZOOM_MEDIUM,
                                        alt_text='First Issue Cover')
    else:
        first_image_tag = None

    return scans, first_image_tag
Esempio n. 4
0
def get_preview_image_tag(revision, alt_text, zoom_level):
    if revision is None:
        return mark_safe('<img class="no_cover" src="' + settings.MEDIA_URL + \
               'img/nocover.gif" alt="No image yet" class="cover_img"/>')

    img_class = 'cover_img'
    if zoom_level == ZOOM_SMALL:
        width = 100
        size = 'small'
        if revision.is_wraparound:
            img_class = 'wraparound_cover_img'
    elif zoom_level == ZOOM_MEDIUM:
        width = 200
        size = 'medium'
        if revision.is_wraparound:
            img_class = 'wraparound_cover_img'
    elif zoom_level == ZOOM_LARGE:
        width = 400
        size = 'large'

    if revision.changeset.state == states.APPROVED:
        current_cover = CoverRevision.objects.filter(
            cover=revision.cover,
            changeset__state=states.APPROVED).order_by('-created')[0]
        if revision == current_cover:
            # Current cover is the one from this revision, show it.
            return get_image_tag(revision.cover, esc(alt_text), zoom_level)
        else:
            # The cover was replaced by now, show original uploaded file,
            # scaled in the browser.
            # It is the real uploaded file for uploads on the new server, and
            # the large scan for older uploads, copied on replacement.
            suffix = "/uploads/%d_%s" % (
                revision.cover.id,
                revision.changeset.created.strftime('%Y%m%d_%H%M%S'))
            if revision.created > settings.NEW_SITE_COVER_CREATION_DATE:
                filename = glob.glob(revision.cover.base_dir() + suffix +
                                     '*')[0]
                file_extension = os.path.splitext(filename)[1]
            else:
                file_extension = ".jpg"
            # TODO:
            suffix = "%d/uploads/%d_%s" % (
                int(revision.cover.id / 1000), revision.cover.id,
                revision.changeset.created.strftime('%Y%m%d_%H%M%S'))
            img_url = settings.IMAGE_SERVER_URL + settings.COVERS_DIR +\
                      suffix + file_extension
            # for old covers do manual scaling, since it is the uploaded file
            return mark_safe('<img src="' + img_url + '" alt="' + \
              esc(alt_text) + '" width="' + str(width) + \
              '" class="' + img_class + '"/>')
    elif revision.deleted:
        return get_image_tag(revision.cover, esc(alt_text), zoom_level)
    else:
        suffix = "w%d/%d.jpg" % (width, revision.id)
        img_url = NEW_COVERS_LOCATION + \
          revision.changeset.created.strftime('%B_%Y/').lower() + suffix
        return mark_safe('<img src="' + img_url + '" alt="' + esc(alt_text) \
               + '" ' + ' class="' + img_class + '"/>')
def get_preview_image_tag(revision, alt_text, zoom_level):
    if revision is None:
        return mark_safe('<img class="no_cover" src="' + settings.MEDIA_URL + \
               'img/nocover.gif" alt="No image yet" class="cover_img"/>')

    img_class = 'cover_img'
    if zoom_level == ZOOM_SMALL:
        width = 100
        size = 'small'
        if revision.is_wraparound:
            img_class = 'wraparound_cover_img'
    elif zoom_level == ZOOM_MEDIUM:
        width = 200
        size = 'medium'
        if revision.is_wraparound:
            img_class = 'wraparound_cover_img'
    elif zoom_level == ZOOM_LARGE:
        width = 400
        size = 'large'

    if revision.changeset.state == states.APPROVED:
        current_cover = CoverRevision.objects.filter(cover=revision.cover, 
          changeset__state=states.APPROVED).order_by('-created')[0]
        if revision==current_cover: 
            # Current cover is the one from this revision, show it.
            return get_image_tag(revision.cover, esc(alt_text), zoom_level)  
        else: 
            # The cover was replaced by now, show original uploaded file,
            # scaled in the browser.
            # It is the real uploaded file for uploads on the new server, and
            # the large scan for older uploads, copied on replacement.
            suffix = "/uploads/%d_%s" % (revision.cover.id, 
                     revision.changeset.created.strftime('%Y%m%d_%H%M%S'))
            if revision.created > settings.NEW_SITE_COVER_CREATION_DATE:
                filename = glob.glob(revision.cover.base_dir() + suffix + '*')[0]
                file_extension = os.path.splitext(filename)[1]
            else:
                file_extension = ".jpg"
            # TODO:
            suffix = "%d/uploads/%d_%s" % (int(revision.cover.id/1000), 
                     revision.cover.id,
                     revision.changeset.created.strftime('%Y%m%d_%H%M%S'))
            img_url = settings.IMAGE_SERVER_URL + settings.COVERS_DIR +\
                      suffix + file_extension
            # for old covers do manual scaling, since it is the uploaded file
            return mark_safe('<img src="' + img_url + '" alt="' + \
              esc(alt_text) + '" width="' + str(width) + \
              '" class="' + img_class + '"/>')
    elif revision.deleted:
        return get_image_tag(revision.cover, esc(alt_text), zoom_level)  
    else:
        suffix = "w%d/%d.jpg" % (width, revision.id)
        img_url = NEW_COVERS_LOCATION + \
          revision.changeset.created.strftime('%B_%Y/').lower() + suffix
        return mark_safe('<img src="' + img_url + '" alt="' + esc(alt_text) \
               + '" ' + ' class="' + img_class + '"/>')
Esempio n. 6
0
 def render_cover(self, value):
     from apps.gcd.views.covers import get_image_tag
     cover_tag = ''
     for cover in value:
         cover_tag += '<a href="%s">%s</a>' % (cover.get_absolute_url(),
                                               get_image_tag(cover, '', 1))
     return mark_safe(cover_tag)
Esempio n. 7
0
def _display_cover_upload_form(request, form, cover, issue, info_text='',
                               variant=False, kwargs=None):
    if kwargs == None:
        kwargs = {}
    upload_template = 'oi/edit/upload_cover.html'
    kwargs['upload_type'] = ''

    if cover:
        kwargs['upload_type'] = 'replacement'
        kwargs['replace_cover'] = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    else:
        if issue.has_covers():
            kwargs['current_covers'] = get_image_tags_per_issue(issue, "current covers",
                                              ZOOM_MEDIUM, as_list=True,
                                              variants=True)
            kwargs['upload_type'] = 'additional'
        if variant:
            kwargs['upload_type'] = 'variant'

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    if issue.variant_of:
        active_covers = CoverRevision.objects\
                        .filter(issue=issue.variant_of,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        active_covers = active_covers | CoverRevision.objects\
                        .filter(issue__variant_of=issue.variant_of,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        if issue.variant_of.has_covers():
            covers_list = get_image_tags_per_issue(issue.variant_of,
                                                   "current covers",
                                                   ZOOM_MEDIUM, as_list=True,
                                                   variants=True)
            if 'current_covers' in kwargs:
                kwargs['current_covers'].extend(covers_list)
            else:
                kwargs['current_covers'] = covers_list
    else:
        active_covers = CoverRevision.objects.filter(issue=issue,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        active_covers = active_covers | CoverRevision.objects\
                        .filter(issue__variant_of=issue,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
    active_covers = active_covers.exclude(changeset__change_type=CTYPES['variant_add'])
    for active_cover in active_covers:
        active_covers_tags.append([active_cover,
                                   get_preview_image_tag(active_cover,
                                     "pending cover", ZOOM_MEDIUM)])
    kwargs['form'] = form
    kwargs['info'] = info_text
    kwargs['cover'] = cover
    kwargs['issue'] = issue
    kwargs['active_covers'] = active_covers_tags
    kwargs['table_width'] = UPLOAD_WIDTH
    return render_to_response(upload_template, kwargs,
                              context_instance=RequestContext(request))
Esempio n. 8
0
def cover(request, issue_id, size):
    """
    Display the cover for a single issue on its own page.
    """

    issue = get_object_or_404(Issue, id = issue_id)
    cover = issue.cover
    [prev_issue, next_issue] = get_prev_next_issue(issue.series, cover)

    cover_tag = get_image_tag(issue.series_id, cover,
                              "Cover Image", int(size))
    style = get_style(request)

    extra = 'cover/' + size + '/' # TODO: remove abstraction-breaking hack.

    return render_to_response(
      'gcd/details/cover.html',
      {
        'issue': issue,
        'prev_issue': prev_issue,
        'next_issue': next_issue,
        'cover_tag': cover_tag,
        'extra': extra,
        'error_subject': '%s cover' % issue,
        'style': style
      },
      context_instance=RequestContext(request)
    )
Esempio n. 9
0
def _display_cover_upload_form(request, form, cover, issue, info_text='',
                               variant=False, kwargs=None):
    if kwargs == None:
        kwargs = {}
    upload_template = 'oi/edit/upload_cover.html'
    kwargs['upload_type'] = ''

    if cover:
        kwargs['upload_type'] = 'replacement'
        kwargs['replace_cover'] = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    else:
        if issue.has_covers():
            kwargs['current_covers'] = get_image_tags_per_issue(issue, "current covers",
                                              ZOOM_MEDIUM, as_list=True,
                                              variants=True)
            kwargs['upload_type'] = 'additional'
        if variant:
            kwargs['upload_type'] = 'variant'

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    if issue.variant_of:
        active_covers = CoverRevision.objects\
                        .filter(issue=issue.variant_of,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        active_covers = active_covers | CoverRevision.objects\
                        .filter(issue__variant_of=issue.variant_of,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        if issue.variant_of.has_covers():
            covers_list = get_image_tags_per_issue(issue.variant_of,
                                                   "current covers",
                                                   ZOOM_MEDIUM, as_list=True,
                                                   variants=True)
            if 'current_covers' in kwargs:
                kwargs['current_covers'].extend(covers_list)
            else:
                kwargs['current_covers'] = covers_list
    else:
        active_covers = CoverRevision.objects.filter(issue=issue,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
        active_covers = active_covers | CoverRevision.objects\
                        .filter(issue__variant_of=issue,
                        changeset__state__in=states.ACTIVE,
                        deleted=False).order_by('created')
    active_covers = active_covers.exclude(changeset__change_type=CTYPES['variant_add'])
    for active_cover in active_covers:
        active_covers_tags.append([active_cover,
                                   get_preview_image_tag(active_cover,
                                     "pending cover", ZOOM_MEDIUM)])
    kwargs['form'] = form
    kwargs['info'] = info_text
    kwargs['cover'] = cover
    kwargs['issue'] = issue
    kwargs['active_covers'] = active_covers_tags
    kwargs['table_width'] = UPLOAD_WIDTH
    return render_to_response(upload_template, kwargs,
                              context_instance=RequestContext(request))
Esempio n. 10
0
def show_series(request, series, preview=False):
    """
    Handle the main work of displaying a series.  Also used by OI previews.
    """
    covers = series.cover_set.select_related('issue')
    issues = series.issue_set.all()

    try:
        cover = covers.filter(has_image=True)[0]
        image_tag = get_image_tag(cover=cover,
                                  zoom_level=ZOOM_MEDIUM,
                                  alt_text='First Issue Cover')

    except IndexError:
        image_tag = ''

    # TODO: Figure out optimal table width and/or make it user controllable.
    table_width = 12

    style = get_style(request)

    return render_to_response('gcd/details/series.html', {
        'series': series,
        'issues': issues,
        'covers': covers,
        'image_tag': image_tag,
        'country': series.country,
        'language': series.language,
        'table_width': table_width,
        'error_subject': '%s' % series,
        'style': style,
        'preview': preview,
    },
                              context_instance=RequestContext(request))
def cover(request, issue_id, size):
    """
    Display the cover for a single issue on its own page.
    """

    issue = get_object_or_404(Issue, id=issue_id)
    cover = issue.cover
    [prev_issue, next_issue] = get_prev_next_issue(issue.series, cover)

    cover_tag = get_image_tag(issue.series_id, cover, "Cover Image", int(size))
    style = get_style(request)

    extra = "cover/" + size + "/"  # TODO: remove abstraction-breaking hack.

    return render_to_response(
        "gcd/details/cover.html",
        {
            "issue": issue,
            "prev_issue": prev_issue,
            "next_issue": next_issue,
            "cover_tag": cover_tag,
            "extra": extra,
            "error_subject": "%s cover" % issue,
            "style": style,
        },
        context_instance=RequestContext(request),
    )
Esempio n. 12
0
def series(request, series_id):
    """
    Display the details page for a series.
    """
    
    series = get_object_or_404(Series, id = series_id)
    covers = series.cover_set.select_related('issue')
    
    try:
        cover = covers.filter(has_medium = True)[0]
        image_tag = get_image_tag(series_id = int(series_id),
                                  cover = cover,
                                  zoom_level = ZOOM_MEDIUM,
                                  alt_text = 'First Issue Cover')
    except IndexError:
        image_tag = ''
        
    try:
        country = Country.objects.get(code__iexact = series.country_code).name
    except:
        country = series.country_code

    # TODO: Fix language table hookup- why is this not a foreign key?
    # For now if we can't get a match in the table then just use the
    # code as itis.
    language = series.language_code
    try:
        lobj = Language.objects.get(code__iexact = series.language_code)
        language = lobj.name
    except:
        pass

    # TODO: Figure out optimal table width and/or make it user controllable.
    table_width = 12

    style = get_style(request)

    return render_to_response(
      'gcd/details/series.html',
      {
        'series' : series,
        'covers' : covers,
        'image_tag' : image_tag,
        'country' : country,
        'language' : language,
        'table_width': table_width,
        'error_subject': '%s' % series,
        'style' : style
      },
      context_instance=RequestContext(request))
def series(request, series_id):
    """
    Display the details page for a series.
    """

    series = get_object_or_404(Series, id=series_id)
    covers = series.cover_set.select_related("issue")

    try:
        cover = covers.filter(has_medium=True)[0]
        image_tag = get_image_tag(
            series_id=int(series_id), cover=cover, zoom_level=ZOOM_MEDIUM, alt_text="First Issue Cover"
        )
    except IndexError:
        image_tag = ""

    try:
        country = Country.objects.get(code__iexact=series.country_code).name
    except:
        country = series.country_code

    # TODO: Fix language table hookup- why is this not a foreign key?
    # For now if we can't get a match in the table then just use the
    # code as itis.
    language = series.language_code
    try:
        lobj = Language.objects.get(code__iexact=series.language_code)
        language = lobj.name
    except:
        pass

    # TODO: Figure out optimal table width and/or make it user controllable.
    table_width = 12

    style = get_style(request)

    return render_to_response(
        "gcd/details/series.html",
        {
            "series": series,
            "covers": covers,
            "image_tag": image_tag,
            "country": country,
            "language": language,
            "table_width": table_width,
            "error_subject": "%s" % series,
            "style": style,
        },
        context_instance=RequestContext(request),
    )
Esempio n. 14
0
def issue(request, issue_id):
    """
    Display the issue details page, including story details.
    """
    issue = get_object_or_404(Issue, id = issue_id)
    cover = issue.cover
    image_tag = get_image_tag(series_id=issue.series.id,
                              cover=cover,
                              zoom_level=ZOOM_SMALL,
                              alt_text='Cover Thumbnail')
    style = get_style(request)

    series = issue.series
    [prev_issue, next_issue] = get_prev_next_issue(series, cover)

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    stories = list(issue.story_set.order_by('sequence_number'))

    cover_story = None
    if (len(stories) > 0):
        cover_story = stories.pop(0)

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)
    oi_indexers = list(set(oi_indexers))

    return render_to_response(
      'gcd/details/issue.html',
      {
        'issue': issue,
        'prev_issue': prev_issue,
        'next_issue': next_issue,
        'cover_story': cover_story,
        'stories': stories,
        'oi_indexers' : oi_indexers,
        'image_tag': image_tag,
        'error_subject': '%s' % issue,
        'style': style,
      },
      context_instance=RequestContext(request))
Esempio n. 15
0
def _get_scan_table(series):
    # all a series' covers + all issues with no covers
    covers = Cover.objects.filter(issue__series=series, deleted=False).select_related()
    issues = series.issues_without_covers()

    scans = list(issues)
    scans.extend(list(covers))
    scans.sort(key=attrgetter('sort_code'))

    if covers:
        first_image_tag = get_image_tag(cover=covers[0], zoom_level=ZOOM_MEDIUM,
                                        alt_text='First Issue Cover')
    else:
        first_image_tag = None

    return scans, first_image_tag
def issue(request, issue_id):
    """
    Display the issue details page, including story details.
    """
    issue = get_object_or_404(Issue, id=issue_id)
    cover = issue.cover
    image_tag = get_image_tag(series_id=issue.series.id, cover=cover, zoom_level=ZOOM_SMALL, alt_text="Cover Thumbnail")
    style = get_style(request)

    series = issue.series
    [prev_issue, next_issue] = get_prev_next_issue(series, cover)

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    stories = list(issue.story_set.order_by("sequence_number"))

    cover_story = None
    if len(stories) > 0:
        cover_story = stories.pop(0)

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)
    oi_indexers = list(set(oi_indexers))

    return render_to_response(
        "gcd/details/issue.html",
        {
            "issue": issue,
            "prev_issue": prev_issue,
            "next_issue": next_issue,
            "cover_story": cover_story,
            "stories": stories,
            "oi_indexers": oi_indexers,
            "image_tag": image_tag,
            "error_subject": "%s" % issue,
            "style": style,
        },
        context_instance=RequestContext(request),
    )
Esempio n. 17
0
def _display_cover_upload_form(request, form, cover, issue, info_text=''):
    upload_template = 'oi/edit/upload_cover.html'

    # set covers, replace_cover, upload_type
    covers = []
    replace_cover = None
    if cover:
        upload_type = 'replacement'
        replace_cover = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    else:
        if issue.has_covers():
            covers = get_image_tags_per_issue(issue,
                                              "current covers",
                                              ZOOM_MEDIUM,
                                              as_list=True)
            upload_type = 'variant'
        else:
            upload_type = ''

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    active_covers = CoverRevision.objects.filter(
        issue=issue, changeset__state__in=states.ACTIVE,
        deleted=False).order_by('created')
    for active_cover in active_covers:
        active_covers_tags.append([
            active_cover,
            get_preview_image_tag(active_cover, "pending cover", ZOOM_MEDIUM)
        ])

    return render_to_response(upload_template, {
        'form': form,
        'info': info_text,
        'cover': cover,
        'issue': issue,
        'current_covers': covers,
        'replace_cover': replace_cover,
        'active_covers': active_covers_tags,
        'upload_type': upload_type,
        'table_width': UPLOAD_WIDTH
    },
                              context_instance=RequestContext(request))
def show_series(request, series, preview=False):
    """
    Handle the main work of displaying a series.  Also used by OI previews.
    """
    if preview:
        covers = Cover.objects.filter(issue__series=series.series)\
                 .select_related('issue')
    else:
        covers = Cover.objects.filter(issue__series=series)\
                 .select_related('issue')
    issues = series.issue_set.all()
    
    try:
        cover = covers.filter(has_image=True)[0]
        image_tag = get_image_tag(cover=cover,
                                  zoom_level=ZOOM_MEDIUM,
                                  alt_text='First Issue Cover')

    except IndexError:
        image_tag = ''
        
    # TODO: Figure out optimal table width and/or make it user controllable.
    table_width = 12

    style = get_style(request)

    return render_to_response(
      'gcd/details/series.html',
      {
        'series': series,
        'issues': issues,
        'covers': covers,
        'image_tag': image_tag,
        'country': series.country,
        'language': series.language,
        'table_width': table_width,
        'error_subject': '%s' % series,
        'style': style,
        'preview': preview,
      },
      context_instance=RequestContext(request))
def _display_cover_upload_form(request, form, cover, issue, info_text=''):
    upload_template = 'oi/edit/upload_cover.html'

    # set covers, replace_cover, upload_type
    covers = []
    replace_cover = None
    if cover:
        upload_type = 'replacement'
        replace_cover = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    else:
        if issue.has_covers():
            covers = get_image_tags_per_issue(issue, "current covers", 
                                              ZOOM_MEDIUM, as_list=True)
            upload_type = 'variant'
        else:
            upload_type = ''

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    active_covers = CoverRevision.objects.filter(issue=issue, 
                    changeset__state__in=states.ACTIVE,
                    deleted=False).order_by('created')
    for active_cover in active_covers:
        active_covers_tags.append([active_cover, 
                                   get_preview_image_tag(active_cover, 
                                     "pending cover", ZOOM_MEDIUM)])

    return render_to_response(upload_template, {
                                'form': form, 
                                'info' : info_text,
                                'cover' : cover,
                                'issue' : issue,
                                'current_covers' : covers,
                                'replace_cover' : replace_cover,
                                'active_covers' : active_covers_tags,
                                'upload_type' : upload_type,
                                'table_width': UPLOAD_WIDTH},
                              context_instance=RequestContext(request))
def upload_cover(request, cover_id=None, issue_id=None):
    """
    Handles uploading of covers be it
    - first upload
    - replacement upload
    - variant upload
    """

    # this cannot actually happen
    if cover_id and issue_id:
        raise ValueError

    upload_template = 'oi/edit/upload_cover.html'
    style = 'default'

    # set cover, issue, covers, replace_cover, upload_type
    covers = []
    replace_cover = None
    # if cover_id is present it is a replacement upload
    if cover_id:
        cover = get_object_or_404(Cover, id=cover_id)
        issue = cover.issue
        if not cover.has_image: 
            # nothing to replace, empty cover slot, redirect to issue upload
            return HttpResponseRedirect(urlresolvers.reverse('upload_cover',
                kwargs={'issue_id': issue.id} ))


        # check if there is a pending change for the cover
        if CoverRevision.objects.filter(cover=cover, 
                                 changeset__state__in=states.ACTIVE):
            revision = CoverRevision.objects.get(cover=cover, 
                                     changeset__state__in=states.ACTIVE)
            return render_error(request,
              ('There currently is a <a href="%s">pending replacement</a> '
               'for this cover of %s.') % (urlresolvers.reverse('compare',
                kwargs={'id': revision.changeset.id}), esc(cover.issue)),
            redirect=False, is_safe=True)

        upload_type = 'replacement'
        replace_cover = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    # no cover_id, therefore upload a cover to an issue (first or variant)
    else: 
        issue = get_object_or_404(Issue, id=issue_id)
        cover = issue.cover_set.latest() # latest can be the empty first one
        if cover.has_image:
            covers = get_image_tags_per_issue(issue, "current covers", 
                                              ZOOM_MEDIUM, as_list=True)
            upload_type = 'variant'
        else:
            upload_type = ''

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    active_covers = CoverRevision.objects.filter(issue=issue, 
                    changeset__state__in=states.ACTIVE).order_by('created')
    for active_cover in active_covers:
        active_covers_tags.append([active_cover, 
                                   get_preview_image_tag(active_cover, 
                                   "pending cover", ZOOM_MEDIUM)])

    # current request is an upload
    if request.method == 'POST':
        try:
            form = UploadScanForm(request.POST,request.FILES)
        except IOError: # sometimes uploads misbehave. connection dropped ?
            error_text = 'Something went wrong with the upload. ' + \
                         'Please <a href="' + request.path + '">try again</a>.'
            return render_error(request, error_text, redirect=False, 
                is_safe=True)

        if not form.is_valid():
            return render_to_response(upload_template, {
                                      'form': form,
                                      'cover' : cover,
                                      'issue' : issue,
                                      'style' : style,
                                      'replace_cover' : replace_cover,
                                      'current_covers' : covers,
                                      'upload_type' : upload_type,
                                      'table_width': UPLOAD_WIDTH
                                      },
                                      context_instance=RequestContext(request))
        # if scan is actually in the form handle it
        if 'scan' in request.FILES:
            # process form
            scan = request.FILES['scan']
            file_source = request.POST['source']
            marked = 'marked' in request.POST

            # create OI records
            changeset = Changeset(indexer=request.user, state=states.PENDING)
            changeset.save()

            if upload_type == 'replacement':
                revision = CoverRevision(changeset=changeset, issue=issue,
                  cover=cover, file_source=file_source, marked=marked,
                  is_replacement = True)
            else:
                revision = CoverRevision(changeset=changeset, issue=issue,
                  file_source=file_source, marked=marked)
            revision.save()

            # put new uploaded covers into 
            # media/<LOCAL_NEW_SCANS>/<monthname>_<year>/ 
            # with name 
            # <revision_id>_<date>_<time>.<ext>
            scan_name = str(revision.id) + os.path.splitext(scan.name)[1]
            upload_dir = settings.MEDIA_ROOT + LOCAL_NEW_SCANS + \
                         changeset.created.strftime('%B_%Y/').lower()
            destination_name = upload_dir + scan_name
            try: # essentially only needed at beginning of the month
                check_cover_dir(upload_dir) 
            except IOError:
                changeset.delete()
                error_text = "Problem with file storage for uploaded " + \
                             "cover, please report an error." 
                return render_error(request, error_text, redirect=False)
 
            # write uploaded file
            destination = open(destination_name, 'wb')
            for chunk in scan.chunks():
                destination.write(chunk)
            destination.close()

            try:
                # generate different sizes we are using
                im = Image.open(destination.name)
                if im.size[0] >= 400:
                    generate_sizes(revision, im)
                else:
                    changeset.delete()
                    os.remove(destination.name)
                    info_text = "Image is too small, only " + str(im.size) + \
                                " in size."
                    return render_to_response(upload_template, {
                      'form': form,
                      'info' : info_text,
                      'cover' : cover,
                      'current_covers' : covers,
                      'replace_cover' : replace_cover,
                      'upload_type' : upload_type,
                      'table_width': UPLOAD_WIDTH,
                      'issue' : issue
                      },
                      context_instance=RequestContext(request))
            except IOError: 
                # just in case, django *should* have taken care of file type
                changeset.delete()
                os.remove(destination.name)
                return render_to_response(upload_template, {
                  'form': form,
                  'info' : 'Error: File \"' + scan.name + \
                           '" is not a valid picture.',
                  'cover' : cover,
                  'issue' : issue,
                  'current_covers' : covers,
                  'replace_cover' : replace_cover,
                  'upload_type' : upload_type,
                  'table_width': UPLOAD_WIDTH
                  },
                  context_instance=RequestContext(request))

            # all done, we can save the state
            changeset.comments.create(commenter=request.user,
                                      text=form.cleaned_data['comments'],
                                      old_state=states.UNRESERVED,
                                      new_state=changeset.state)

            if 'remember_source' in request.POST:
                request.session['oi_file_source'] = request.POST['source']
            else:
                request.session.pop('oi_file_source','')

            return HttpResponseRedirect(urlresolvers.reverse('upload_cover_complete',
                kwargs={'revision_id': revision.id} ))

    # request is a GET for the form
    else:
        if 'oi_file_source' in request.session:
            vars = {'source' : request.session['oi_file_source'],
                    'remember_source' : True}
        else:
            vars = None
        form = UploadScanForm(initial=vars)

        # display the form
        return render_to_response(upload_template, {
                                  'form': form, 
                                  'cover' : cover,
                                  'issue' : issue,
                                  'current_covers' : covers,
                                  'replace_cover' : replace_cover,
                                  'active_covers' : active_covers_tags,
                                  'upload_type' : upload_type,
                                  'table_width': UPLOAD_WIDTH},
                                  context_instance=RequestContext(request))
Esempio n. 21
0
def show_issue(request, issue, preview=False):
    """
    Helper function to handle the main work of displaying an issue.
    Also used by OI previews.
    """
    alt_text = u'Cover Thumbnail for %s' % issue.full_name()
    zoom_level = ZOOM_MEDIUM
    if preview:
        images_count = 0
        # excludes are currently only relevant for variant_add, maybe later
        # other cover moves will be possible
        if issue.changeset.change_type in [CTYPES['variant_add'],
                                           CTYPES['two_issues']] and \
          issue.changeset.coverrevisions.count():
            # need to exclude the moved one
            image_tag = mark_safe('')
            if issue.issue and issue.issue.active_covers().count():
                exclude_ids = issue.changeset.coverrevisions\
                .filter(issue=issue.issue).values_list('cover__id', flat=True)
                if len(exclude_ids) < issue.issue.active_covers().count():
                    image_tag = get_image_tags_per_issue(
                        issue=issue.issue,
                        zoom_level=zoom_level,
                        alt_text=alt_text,
                        exclude_ids=exclude_ids)
            # add moved cover(s)
            for cover in issue.changeset.coverrevisions\
                                        .exclude(issue=issue.issue):
                image_tag += get_image_tag(cover.cover,
                                           alt_text=alt_text,
                                           zoom_level=zoom_level)
            if image_tag == '':
                image_tag = mark_safe(
                    get_image_tag(cover=None,
                                  zoom_level=zoom_level,
                                  alt_text=alt_text))
        elif issue.issue:
            image_tag = get_image_tags_per_issue(issue=issue.issue,
                                                 zoom_level=zoom_level,
                                                 alt_text=alt_text)
            images_count = Image.objects.filter(object_id=issue.issue.id,
              deleted=False,
              content_type = ContentType.objects.get_for_model(issue.issue))\
                                        .count()
        else:
            image_tag = mark_safe(
                get_image_tag(cover=None,
                              zoom_level=zoom_level,
                              alt_text=alt_text))
    else:
        image_tag = get_image_tags_per_issue(issue=issue,
                                             zoom_level=zoom_level,
                                             alt_text=alt_text)
        images_count = Image.objects.filter(
            object_id=issue.id,
            deleted=False,
            content_type=ContentType.objects.get_for_model(issue)).count()

    variant_image_tags = []
    for variant_cover in issue.variant_covers():
        variant_image_tags.append([
            variant_cover.issue,
            get_image_tag(variant_cover,
                          zoom_level=ZOOM_SMALL,
                          alt_text=u'Cover Thumbnail for %s' %
                          unicode(variant_cover.issue))
        ])

    series = issue.series
    [prev_issue, next_issue] = issue.get_prev_next_issue()

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    cover_story, stories = issue.shown_stories()

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)

    if preview:
        if issue.issue:
            res = IssueRevision.objects.filter(issue=issue.issue)
        else:
            res = IssueRevision.objects.none()
    else:
        res = IssueRevision.objects.filter(issue=issue)
    res = res.filter(changeset__state=states.APPROVED)\
             .exclude(changeset__indexer__username=settings.ANON_USER_NAME)
    for i in res:
        oi_indexers.append(i.changeset.indexer.indexer)
    oi_indexers = list(set(oi_indexers))

    show_original = False
    if (request.GET.has_key('original_reprint_notes')):
        if request.GET['original_reprint_notes'] == 'True':
            show_original = True

    return render_to_response('gcd/details/issue.html', {
        'issue': issue,
        'prev_issue': prev_issue,
        'next_issue': next_issue,
        'cover_story': cover_story,
        'stories': stories,
        'oi_indexers': oi_indexers,
        'image_tag': image_tag,
        'variant_image_tags': variant_image_tags,
        'images_count': images_count,
        'show_original': show_original,
        'error_subject': '%s' % issue,
        'preview': preview,
    },
                              context_instance=RequestContext(request))
Esempio n. 22
0
def show_issue(request, issue, preview=False):
    """
    Helper function to handle the main work of displaying an issue.
    Also used by OI previews.
    """
    alt_text = u'Cover Thumbnail for %s' % issue.full_name()
    zoom_level = ZOOM_MEDIUM
    if preview:
        images_count = 0
        not_shown_types = []
        # excludes are currently only relevant for variant_add, maybe later
        # other cover moves will be possible
        if issue.changeset.change_type in [CTYPES['variant_add'],
                                           CTYPES['two_issues']] and \
          issue.changeset.coverrevisions.count():
            # need to exclude the moved one
            image_tag = mark_safe('')
            if issue.issue and issue.issue.active_covers().count():
                exclude_ids = issue.changeset.coverrevisions\
                .filter(issue=issue.issue).values_list('cover__id', flat=True)
                if len(exclude_ids) < issue.issue.active_covers().count():
                    image_tag = get_image_tags_per_issue(issue=issue.issue,
                                  zoom_level=zoom_level,
                                  alt_text=alt_text,
                                  exclude_ids=exclude_ids)
            # add moved cover(s)
            for cover in issue.changeset.coverrevisions\
                                        .exclude(issue=issue.issue):
                image_tag += get_image_tag(cover.cover,
                                           alt_text=alt_text,
                                           zoom_level=zoom_level)
            if image_tag == '':
                image_tag = mark_safe(get_image_tag(cover=None,
                                                    zoom_level=zoom_level,
                                                    alt_text=alt_text))
        elif issue.issue:
            image_tag = get_image_tags_per_issue(issue=issue.issue,
                                                 zoom_level=zoom_level,
                                                 alt_text=alt_text)
            images_count = Image.objects.filter(object_id=issue.issue.id, 
              deleted=False, 
              content_type = ContentType.objects.get_for_model(issue.issue))\
                                        .count()
        else:
            image_tag = mark_safe(get_image_tag(cover=None,
                                                zoom_level=zoom_level,
                                                alt_text=alt_text))
    else:
        if 'issue_detail' in request.GET:
            try:
                issue_detail = int(request.GET['issue_detail'])
            except ValueError:
                issue_detail = 1
        elif request.user.is_authenticated():
            issue_detail = request.user.indexer.issue_detail
        else:
            issue_detail = 1
        if issue_detail == 0:
            not_shown_types = StoryType.objects.exclude(id__in=CORE_TYPES)\
                                .values_list('id', flat=True)
        elif issue_detail == 1:
            not_shown_types = AD_TYPES
        else:
            not_shown_types = []
        image_tag = get_image_tags_per_issue(issue=issue,
                                             zoom_level=zoom_level,
                                             alt_text=alt_text)
        images_count = Image.objects.filter(object_id=issue.id, deleted=False,
          content_type = ContentType.objects.get_for_model(issue)).count()

    variant_image_tags = []
    for variant_cover in issue.variant_covers():
        variant_image_tags.append([variant_cover.issue,
          get_image_tag(variant_cover, zoom_level=ZOOM_SMALL,
          alt_text=u'Cover Thumbnail for %s' % unicode(variant_cover.issue))])

    series = issue.series
    [prev_issue, next_issue] = issue.get_prev_next_issue()

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    cover_story, stories = issue.shown_stories()

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)

    if preview:
        if issue.issue:
            res = IssueRevision.objects.filter(issue=issue.issue)
        else:
            res = IssueRevision.objects.none()
    else:
        res = IssueRevision.objects.filter(issue=issue)
    res = res.filter(changeset__state=states.APPROVED)\
             .exclude(changeset__indexer__username=settings.ANON_USER_NAME)
    for i in res:
        oi_indexers.append(i.changeset.indexer.indexer)
    oi_indexers = list(set(oi_indexers))

    show_original = False
    if (request.GET.has_key('original_reprint_notes')):
        if request.GET['original_reprint_notes'] == 'True':
            show_original = True

    if series.is_singleton:
        country = series.country
        language = series.language
    else:
        country = None
        language = None

    return render_to_response(
      'gcd/details/issue.html',
      {
        'issue': issue,
        'prev_issue': prev_issue,
        'next_issue': next_issue,
        'cover_story': cover_story,
        'stories': stories,
        'oi_indexers' : oi_indexers,
        'image_tag': image_tag,
        'variant_image_tags': variant_image_tags,
        'images_count': images_count,
        'show_original': show_original,
        'country': country,
        'language': language,
        'error_subject': '%s' % issue,
        'preview': preview,
        'not_shown_types': not_shown_types,
        'NO_ADS': True
      },
      context_instance=RequestContext(request))
Esempio n. 23
0
def show_issue(request, issue, preview=False):
    """
    Helper function to handle the main work of displaying an issue.
    Also used by OI previews.
    """
    alt_text = u"Cover Thumbnail for %s" % issue.full_name()
    zoom_level = ZOOM_MEDIUM
    if preview:
        images_count = 0
        # excludes are currently only relevant for variant_add, maybe later
        # other cover moves will be possible
        if (
            issue.changeset.change_type in [CTYPES["variant_add"], CTYPES["two_issues"]]
            and issue.changeset.coverrevisions.count()
        ):
            # need to exclude the moved one
            image_tag = mark_safe("")
            if issue.issue and issue.issue.active_covers().count():
                exclude_ids = issue.changeset.coverrevisions.filter(issue=issue.issue).values_list(
                    "cover__id", flat=True
                )
                if len(exclude_ids) < issue.issue.active_covers().count():
                    image_tag = get_image_tags_per_issue(
                        issue=issue.issue, zoom_level=zoom_level, alt_text=alt_text, exclude_ids=exclude_ids
                    )
            # add moved cover(s)
            for cover in issue.changeset.coverrevisions.exclude(issue=issue.issue):
                image_tag += get_image_tag(cover.cover, alt_text=alt_text, zoom_level=zoom_level)
            if image_tag == "":
                image_tag = mark_safe(get_image_tag(cover=None, zoom_level=zoom_level, alt_text=alt_text))
        elif issue.issue:
            image_tag = get_image_tags_per_issue(issue=issue.issue, zoom_level=zoom_level, alt_text=alt_text)
            images_count = Image.objects.filter(
                object_id=issue.issue.id, deleted=False, content_type=ContentType.objects.get_for_model(issue.issue)
            ).count()
        else:
            image_tag = mark_safe(get_image_tag(cover=None, zoom_level=zoom_level, alt_text=alt_text))
    else:
        image_tag = get_image_tags_per_issue(issue=issue, zoom_level=zoom_level, alt_text=alt_text)
        images_count = Image.objects.filter(
            object_id=issue.id, deleted=False, content_type=ContentType.objects.get_for_model(issue)
        ).count()

    variant_image_tags = []
    for variant_cover in issue.variant_covers():
        variant_image_tags.append(
            [
                variant_cover.issue,
                get_image_tag(
                    variant_cover,
                    zoom_level=ZOOM_SMALL,
                    alt_text=u"Cover Thumbnail for %s" % unicode(variant_cover.issue),
                ),
            ]
        )

    series = issue.series
    [prev_issue, next_issue] = issue.get_prev_next_issue()

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    cover_story, stories = issue.shown_stories()

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)

    if preview:
        if issue.issue:
            res = IssueRevision.objects.filter(issue=issue.issue)
        else:
            res = IssueRevision.objects.none()
    else:
        res = IssueRevision.objects.filter(issue=issue)
    res = res.filter(changeset__state=states.APPROVED).exclude(changeset__indexer__username=settings.ANON_USER_NAME)
    for i in res:
        oi_indexers.append(i.changeset.indexer.indexer)
    oi_indexers = list(set(oi_indexers))

    show_original = False
    if request.GET.has_key("original_reprint_notes"):
        if request.GET["original_reprint_notes"] == "True":
            show_original = True

    return render_to_response(
        "gcd/details/issue.html",
        {
            "issue": issue,
            "prev_issue": prev_issue,
            "next_issue": next_issue,
            "cover_story": cover_story,
            "stories": stories,
            "oi_indexers": oi_indexers,
            "image_tag": image_tag,
            "variant_image_tags": variant_image_tags,
            "images_count": images_count,
            "show_original": show_original,
            "error_subject": "%s" % issue,
            "preview": preview,
        },
        context_instance=RequestContext(request),
    )
Esempio n. 24
0
def cover_image_tag(cover, size_alt_text):
    size, alt_text = size_alt_text.split(',')
    return get_image_tag(cover, alt_text, int(size))
Esempio n. 25
0
def upload_cover(request, cover_id=None, issue_id=None):
    """
    Handles uploading of covers be it
    - first upload
    - replacement upload
    - variant upload
    """

    # this cannot actually happen
    if cover_id and issue_id:
        raise ValueError

    upload_template = 'oi/edit/upload_cover.html'
    style = 'default'

    # set cover, issue, covers, replace_cover, upload_type
    covers = []
    replace_cover = None
    # if cover_id is present it is a replacement upload
    if cover_id:
        cover = get_object_or_404(Cover, id=cover_id)
        issue = cover.issue

        # check if there is a pending change for the cover
        if CoverRevision.objects.filter(cover=cover,
                                        changeset__state__in=states.ACTIVE):
            revision = CoverRevision.objects.get(
                cover=cover, changeset__state__in=states.ACTIVE)
            return render_error(
                request,
                ('There currently is a <a href="%s">pending replacement</a> '
                 'for this cover of %s.') % (urlresolvers.reverse(
                     'compare', kwargs={'id': revision.changeset.id
                                        }), esc(cover.issue)),
                redirect=False,
                is_safe=True)

        upload_type = 'replacement'
        replace_cover = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM)
    # no cover_id, therefore upload a cover to an issue (first or variant)
    else:
        issue = get_object_or_404(Issue, id=issue_id)
        cover = None
        if issue.has_covers():
            covers = get_image_tags_per_issue(issue,
                                              "current covers",
                                              ZOOM_MEDIUM,
                                              as_list=True)
            upload_type = 'variant'
        else:
            upload_type = ''

    # generate tags for cover uploads for this issue currently in the queue
    active_covers_tags = []
    active_covers = CoverRevision.objects.filter(
        issue=issue, changeset__state__in=states.ACTIVE,
        deleted=False).order_by('created')
    for active_cover in active_covers:
        active_covers_tags.append([
            active_cover,
            get_preview_image_tag(active_cover, "pending cover", ZOOM_MEDIUM)
        ])

    # current request is an upload
    if request.method == 'POST':
        try:
            form = UploadScanForm(request.POST, request.FILES)
        except IOError:  # sometimes uploads misbehave. connection dropped ?
            error_text = 'Something went wrong with the upload. ' + \
                         'Please <a href="' + request.path + '">try again</a>.'
            return render_error(request,
                                error_text,
                                redirect=False,
                                is_safe=True)

        if not form.is_valid():
            return render_to_response(upload_template, {
                'form': form,
                'cover': cover,
                'issue': issue,
                'style': style,
                'replace_cover': replace_cover,
                'current_covers': covers,
                'upload_type': upload_type,
                'table_width': UPLOAD_WIDTH
            },
                                      context_instance=RequestContext(request))
        # if scan is actually in the form handle it
        if 'scan' in request.FILES:
            # process form
            scan = request.FILES['scan']
            file_source = request.POST['source']
            marked = 'marked' in request.POST

            # create OI records
            changeset = Changeset(indexer=request.user,
                                  state=states.PENDING,
                                  change_type=CTYPES['cover'])
            changeset.save()

            if upload_type == 'replacement':
                revision = CoverRevision(changeset=changeset,
                                         issue=issue,
                                         cover=cover,
                                         file_source=file_source,
                                         marked=marked,
                                         is_replacement=True)
            else:
                revision = CoverRevision(changeset=changeset,
                                         issue=issue,
                                         file_source=file_source,
                                         marked=marked)
            revision.save()

            # put new uploaded covers into
            # media/<LOCAL_NEW_SCANS>/<monthname>_<year>/
            # with name
            # <revision_id>_<date>_<time>.<ext>
            scan_name = str(revision.id) + os.path.splitext(scan.name)[1]
            upload_dir = settings.MEDIA_ROOT + LOCAL_NEW_SCANS + \
                         changeset.created.strftime('%B_%Y/').lower()
            destination_name = upload_dir + scan_name
            try:  # essentially only needed at beginning of the month
                check_cover_dir(upload_dir)
            except IOError:
                changeset.delete()
                error_text = "Problem with file storage for uploaded " + \
                             "cover, please report an error."
                return render_error(request, error_text, redirect=False)

            # write uploaded file
            destination = open(destination_name, 'wb')
            for chunk in scan.chunks():
                destination.write(chunk)
            destination.close()

            try:
                # generate different sizes we are using
                im = Image.open(destination.name)
                if im.size[0] >= 400:
                    generate_sizes(revision, im)
                else:
                    changeset.delete()
                    os.remove(destination.name)
                    info_text = "Image is too small, only " + str(im.size) + \
                                " in size."
                    return render_to_response(
                        upload_template, {
                            'form': form,
                            'info': info_text,
                            'cover': cover,
                            'current_covers': covers,
                            'replace_cover': replace_cover,
                            'upload_type': upload_type,
                            'table_width': UPLOAD_WIDTH,
                            'issue': issue
                        },
                        context_instance=RequestContext(request))
            except IOError:
                # just in case, django *should* have taken care of file type
                changeset.delete()
                os.remove(destination.name)
                return render_to_response(upload_template, {
                  'form': form,
                  'info' : 'Error: File \"' + scan.name + \
                           '" is not a valid picture.',
                  'cover' : cover,
                  'issue' : issue,
                  'current_covers' : covers,
                  'replace_cover' : replace_cover,
                  'upload_type' : upload_type,
                  'table_width': UPLOAD_WIDTH
                  },
                  context_instance=RequestContext(request))

            # all done, we can save the state
            changeset.comments.create(commenter=request.user,
                                      text=form.cleaned_data['comments'],
                                      old_state=states.UNRESERVED,
                                      new_state=changeset.state)

            if 'remember_source' in request.POST:
                request.session['oi_file_source'] = request.POST['source']
            else:
                request.session.pop('oi_file_source', '')

            return HttpResponseRedirect(
                urlresolvers.reverse('upload_cover_complete',
                                     kwargs={'revision_id': revision.id}))

    # request is a GET for the form
    else:
        if 'oi_file_source' in request.session:
            vars = {
                'source': request.session['oi_file_source'],
                'remember_source': True
            }
        else:
            vars = None
        form = UploadScanForm(initial=vars)

        # display the form
        return render_to_response(upload_template, {
            'form': form,
            'cover': cover,
            'issue': issue,
            'current_covers': covers,
            'replace_cover': replace_cover,
            'active_covers': active_covers_tags,
            'upload_type': upload_type,
            'table_width': UPLOAD_WIDTH
        },
                                  context_instance=RequestContext(request))
def show_issue(request, issue, preview=False):
    """
    Handle the main work of displaying an issue.  Also used by OI previews.
    """
    alt_text = 'Cover Thumbnail'
    zoom_level = ZOOM_MEDIUM
    if preview:
        # excludes are currently only relevant for variant_add, maybe later
        # other cover moves will be possible
        if issue.changeset.change_type in [CTYPES['variant_add'],
                                           CTYPES['two_issues']] and \
          issue.changeset.coverrevisions.count():
            # need to exclude the moved one
            image_tag = mark_safe('')
            if issue.issue and issue.issue.active_covers().count():
                exclude_ids = issue.changeset.coverrevisions\
                .filter(issue=issue.issue).values_list('cover__id', flat=True)
                if len(exclude_ids) < issue.issue.active_covers().count():
                    image_tag = get_image_tags_per_issue(issue=issue.issue,
                                  zoom_level=zoom_level,
                                  alt_text=alt_text,
                                  exclude_ids=exclude_ids)
            # add moved cover(s)
            for cover in issue.changeset.coverrevisions\
                                        .exclude(issue=issue.issue):
                image_tag += get_image_tag(cover.cover,
                                           alt_text=alt_text,
                                           zoom_level=zoom_level)
            if image_tag == '':
                image_tag = mark_safe(get_image_tag(cover=None,
                                                    zoom_level=zoom_level,
                                                    alt_text=alt_text))
        elif issue.issue:
            image_tag = get_image_tags_per_issue(issue=issue.issue,
                                                 zoom_level=zoom_level,
                                                 alt_text=alt_text)
        else:
            image_tag = mark_safe(get_image_tag(cover=None,
                                                zoom_level=zoom_level,                                           alt_text=alt_text))
    else:
        image_tag = get_image_tags_per_issue(issue=issue,
                                             zoom_level=zoom_level,
                                             alt_text=alt_text)

    variant_image_tags = []
    for variant_cover in issue.variant_covers():
        variant_image_tags.append([variant_cover.issue,
                                   get_image_tag(variant_cover,
                                                 zoom_level=ZOOM_SMALL,
                                                 alt_text='Cover Thumbnail')])

    series = issue.series
    [prev_issue, next_issue] = issue.get_prev_next_issue()

    # TODO: Since the number of stories per issue is typically fairly small,
    # it seems more efficient to grab the whole list and only do one database
    # query rather than separately select the cover story and the interior
    # stories.  But we should measure this.  Note that we definitely want
    # to send the cover and interior stories to the UI separately, as the
    # UI should not be concerned with the designation of story 0 as the cover.
    cover_story, stories = issue.shown_stories()

    # get reservations which got approved and make unique for indexers
    res = issue.reservation_set.filter(status=3)
    oi_indexers = []
    for i in res:
        oi_indexers.append(i.indexer)

    if preview:
        if issue.issue:
            res = IssueRevision.objects.filter(issue=issue.issue)
        else:
            res = IssueRevision.objects.none()
    else:
        res = IssueRevision.objects.filter(issue=issue)
    res = res.filter(changeset__state=states.APPROVED)\
             .exclude(changeset__indexer__username=settings.ANON_USER_NAME)
    for i in res:
        oi_indexers.append(i.changeset.indexer.indexer)
    oi_indexers = list(set(oi_indexers))

    return render_to_response(
      'gcd/details/issue.html',
      {
        'issue': issue,
        'prev_issue': prev_issue,
        'next_issue': next_issue,
        'cover_story': cover_story,
        'stories': stories,
        'oi_indexers' : oi_indexers,
        'image_tag': image_tag,
        'variant_image_tags': variant_image_tags,
        'error_subject': '%s' % issue,
        'preview': preview,
      },
      context_instance=RequestContext(request))