Skip to content

Commit

Permalink
openlibhums#1322: most downloaded article (pr openlibhums#1344)
Browse files Browse the repository at this point in the history
* Partial commit.

* Form now works as expected.

* Initial pass over.

* Changed title on OLH theme

* Switched to Processed Values.

* Fixed query.

* Partial: adds dt filtering.

* openlibhums#1322: Use natural join filters instead of subquery

* When articles have the same number of accesses, order by title.

* Brought most popular articles to Default and Material.

* Reset featured.

* Resets featured templates.

* Added new popular homepage element.
  • Loading branch information
ajrbyers authored and mauromsl committed Nov 14, 2019
1 parent 2219c27 commit ce76f58
Show file tree
Hide file tree
Showing 13 changed files with 459 additions and 1 deletion.
Empty file.
66 changes: 66 additions & 0 deletions src/core/homepage_elements/popular/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from django import forms

from utils import setting_handler
from core.homepage_elements.popular import plugin_settings, logic


class FeaturedForm(forms.Form):

def __init__(self, *args, **kwargs):
self.journal = kwargs.pop('journal', None)
super(FeaturedForm, self).__init__(*args, **kwargs)

most_popular, num_most_popular, most_popular_time = logic.get_popular_article_settings(
self.journal
)

self.fields['num_most_popular'].initial = num_most_popular
self.fields['most_popular'].initial = most_popular
self.fields['most_popular_time'].initial = most_popular_time

most_popular = forms.BooleanField(
label='Display Most Popular Articles',
help_text='Displays the most popular articles.',
required=False,
)
num_most_popular = forms.IntegerField(
label='Number of Most Popular Articles to Display',
help_text='Determines how many popular articles we should display.',
)
most_popular_time = forms.ChoiceField(
choices=(
('weekly', 'Weekly'),
('monthly', 'Monthly'),
('yearly', 'Yearly'),
),
label='Number of Most Popular Articles to Display',
help_text='Determines how many popular articles we should display.',
)

def save(self, commit=True):
most_popular = self.cleaned_data.get('most_popular')
num_most_popular = self.cleaned_data.get('num_most_popular', 0)
most_popular_time = self.cleaned_data.get('most_popular_time')

if commit:
setting_handler.save_plugin_setting(
plugin_settings.get_self(),
'most_popular',
most_popular,
self.journal,
)

setting_handler.save_plugin_setting(
plugin_settings.get_self(),
'num_most_popular',
num_most_popular,
self.journal,
)

setting_handler.save_plugin_setting(
plugin_settings.get_self(),
'most_popular_time',
most_popular_time,
self.journal,
)

24 changes: 24 additions & 0 deletions src/core/homepage_elements/popular/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from core.homepage_elements.popular import logic


def yield_homepage_element_context(request, homepage_elements):
if homepage_elements is not None and homepage_elements.filter(
name='Popular Articles',
).exists():

most_popular, number, time = logic.get_popular_article_settings(
request.journal
)

popular_articles = logic.get_most_popular_articles(
request.journal,
number,
time,
)

return {
'popular_articles': popular_articles,
'most_popular': most_popular,
}
else:
return {}
67 changes: 67 additions & 0 deletions src/core/homepage_elements/popular/logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from datetime import timedelta

from django.db.models import Count
from django.utils import timezone

from submission import models as sm
from utils import setting_handler
from core.homepage_elements.popular import plugin_settings


def get_popular_article_settings(journal):
plugin = plugin_settings.get_self()

try:
most_popular = setting_handler.get_plugin_setting(
plugin,
'most_popular',
journal,
).processed_value
except IndexError:
most_popular = False

try:
num_most_popular = setting_handler.get_plugin_setting(
plugin,
'num_most_popular',
journal,
).processed_value
except IndexError:
num_most_popular = 0
try:
most_popular_time = setting_handler.get_plugin_setting(
plugin,
'most_popular_time',
journal,
).processed_value
except IndexError:
most_popular_time = 'weekly'

return most_popular, num_most_popular, most_popular_time


def calc_start_date(time):
date_time = timezone.now()

if time == 'weekly':
delta = 7
elif time == 'monthly':
delta = 30
else:
delta = 365

return date_time - timedelta(days=delta)


def get_most_popular_articles(journal, number, time):
start_date = calc_start_date(time)

articles = sm.Article.objects.filter(
journal=journal,
stage=sm.STAGE_PUBLISHED,
articleaccess__accessed__gte=start_date,
).annotate(
access_count=Count("articleaccess")
).order_by('-access_count', 'title')[:number]

return articles
Empty file.
107 changes: 107 additions & 0 deletions src/core/homepage_elements/popular/plugin_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from django.db.utils import OperationalError
from django.contrib.contenttypes.models import ContentType

from utils import models
from utils.logger import get_logger

logger = get_logger(__name__)

PLUGIN_NAME = 'Popular Articles'
DESCRIPTION = 'This is a homepage element that renders popular articles.'
AUTHOR = 'Martin Paul Eve'
VERSION = '1.0'


def get_self():
try:
plugin = models.Plugin.objects.get(
name=PLUGIN_NAME,
)
return plugin
except models.Plugin.DoesNotExist:
return None


def install():
import core.models as core_models
import journal.models as journal_models

plugin, c = models.Plugin.objects.get_or_create(
name=PLUGIN_NAME,
version=VERSION,
enabled=True,
display_name='Popular Articles',
homepage_element=True,
)

if c:
logger.debug('Plugin {} created'.format(PLUGIN_NAME))

models.PluginSetting.objects.get_or_create(
name='most_popular',
plugin=plugin,
defaults={
'pretty_name': 'Display Most Popular Articles',
'types': 'boolean',
'description': 'Displays the most popular articles.',
'is_translatable': False,
}
)

models.PluginSetting.objects.get_or_create(
name='num_most_popular',
plugin=plugin,
defaults={
'pretty_name': 'Number of Most Popular Articles to Display',
'types': 'number',
'description': 'Determines how many popular articles we should display.',
'is_translatable': False,
}
)

models.PluginSetting.objects.get_or_create(
name='most_popular_time',
plugin=plugin,
defaults={
'pretty_name': 'Most Popular Timescale',
'types': 'text',
'description': 'Select from this week, this month or this year.',
'is_translatable': False,
}
)

if c:
logger.debug('Setting created')

# check whether this homepage element has already been installed for all journals
journals = journal_models.Journal.objects.all()

for journal in journals:
content_type = ContentType.objects.get_for_model(journal)
element, created = core_models.HomepageElement.objects.get_or_create(
name=PLUGIN_NAME,
configure_url='popular_articles_setup',
template_path='journal/homepage_elements/popular.html',
content_type=content_type,
object_id=journal.pk,
has_config=True,
)

element.save()


def hook_registry():
try:
install()
return {
'yield_homepage_element_context': {
'module': 'core.homepage_elements.popular.hooks',
'function': 'yield_homepage_element_context',
'name': PLUGIN_NAME,
}
}
except OperationalError:
# if we get here the database hasn't yet been created
return {}
except BaseException:
return {}
41 changes: 41 additions & 0 deletions src/core/homepage_elements/popular/templates/popular_setup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "admin/core/base.html" %}
{% load foundation %}
{% load static from staticfiles %}

{% block title %}Popular Articles Manager{% endblock title %}
{% block admin-header %}Popular Articles Manager{% endblock %}

{% block breadcrumbs %}
{{ block.super }}
<li><a href="{% url 'core_manager_index' %}">Manager</a></li>
<li><a href="{% url 'home_settings_index' %}">Journal Home Settings</a></li>
<li>Popular Articles Manager</li>
{% endblock %}

{% block body %}
<div class="box">
<div class="title-area">
<h2>Display Most Popular Articles</h2>
</div>
<div class="content">
<div class="row expanded">
<div class="large-6 columns">
<p>You can override the display of this block with the most popular articles rather than
featured.</p>
<form method="POST">
{% csrf_token %}
{{ form|foundation }}
<button name="form" class="success button">Save</button>
</form>
</div>
</div>

</div>
</div>
{% endblock body %}

{% block js %}
{% include "elements/datatables.html" with target="#featured" %}
{% endblock js %}


7 changes: 7 additions & 0 deletions src/core/homepage_elements/popular/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.conf.urls import url
from core.homepage_elements.popular import views

urlpatterns = [
# Featured Articles
url(r'^manager/$', views.featured_articles, name='popular_articles_setup'),
]
33 changes: 33 additions & 0 deletions src/core/homepage_elements/popular/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.urls import reverse
from django.shortcuts import redirect, render
from django.contrib import messages

from core.homepage_elements.popular import forms

from security.decorators import editor_user_required


@editor_user_required
def featured_articles(request):
form = forms.FeaturedForm(journal=request.journal)

if request.POST:

if 'form' in request.POST:
form = forms.FeaturedForm(request.POST, journal=request.journal)

if form.is_valid():
form.save()
messages.add_message(
request,
messages.SUCCESS,
'Settings saved.',
)
return redirect(reverse('popular_articles_setup'))

template = 'popular_setup.html'
context = {
'form': form,
}

return render(request, template, context)
40 changes: 40 additions & 0 deletions src/themes/OLH/templates/journal/homepage_elements/popular.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% load static from staticfiles %}
{% load i18n %}

<section>
<div class="row column text-center">
{% if most_downloaded %}
<h2 class="title">{% trans 'Most Popular Articles' %}</h2>
{% else %}
<h2 class="title">{% trans 'Featured Articles' %}</h2>
{% endif %}
</div>
<div class="row" data-equalizer data-equalize-on="medium">
{% for article in popular_articles %}
<div class="large-4 columns{% if forloop.last %} end{% endif %}" >
<div class="box" data-equalizer-watch>
<a href="{% if article.is_remote %}{{ article.remote_url }}{% else %}{{ article.url }}{% endif %}"
class="box-link"></a>

{% if article.large_image_file %}
<img src="{% url 'article_file_download' 'id' article.id article.large_image_file.id %}"
alt="{{ article.title|striptags }}" class="feature-article-image">
{% elif article.journal.default_large_image %}
<img src="{{ article.journal.default_large_image.url }}"
alt="{{ article.title|striptags }}" class="feature-article-image">
{% else %}
<img src="{% static 'common/img/sample/article-small.jpg' %}"
alt="{{ article.title|striptags }}" class="feature-article-image">
{% endif %}

<div class="content">
<p>{{ article.author_list }}</p>
<p><strong>{{ article.title|safe|truncatechars:200 }}</strong></p>
</div>
</div>
</div>
{% if forloop.counter|divisibleby:3 %}</div>
<div class="row">{% endif %}
{% endfor %}
</div>
</section>
Loading

0 comments on commit ce76f58

Please sign in to comment.