Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paper assignment page #2756

Merged
merged 8 commits into from Jan 11, 2017
Merged

Conversation

mvidalgarcia
Copy link
Member

@mvidalgarcia mvidalgarcia commented Dec 9, 2016

WIP:

  • Filter by state
  • Add optional columns: Contribution type, session
  • Filter by Track, Contribution type, session
  • Extra filters: Material submitted
  • Bulk change state
  • Update headers in new files by running python bin/maintenance/update_header.py 2017

@nop33 nop33 self-assigned this Dec 9, 2016
@@ -34,6 +34,7 @@
methods=('GET', 'POST'))
_bp.add_url_rule('/manage/papers/enable/<any(content,layout):reviewing_type>', 'switch',
management.RHSwitchReviewingType, methods=('PUT', 'DELETE'))
_bp.add_url_rule('/manage/papers/assign', 'assignment', management.RHPapersAssignment)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use RHPaperAssignmentList and /manage/papers/assignment-list/

{% if contrib.paper_revisions %}
{{ contrib.paper_revisions.0.state.title }}
{% else %}
{%- trans %}Paper not yet submitted{% endtrans -%}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some places you use - to remove the whitespace and in others you don't. I'd suggest to stick to one of the two conventions. The best IMO is to remove the whitespace because it creates an ugly HTML structure.

{% for contrib in contribs %}
{% set last_revision_state %}
{% if contrib.paper_revisions %}
{{ contrib.paper_revisions.0.state.title }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this even work? ❗

Why not {{ contrib.paper_revisions[0].state.title }}?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have a property in the contribution model to retrieve the latest revision...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, please do not use .0. in jinja but [0] instead. And yes, we should have a property/relationship that takes care of it. Since the relationship is slighly tricky - but albeit very useful so we can joinedload it e.g. for the listing - I would first go for a simple property and then change it to a relationship later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThiefMaster, muy importante.

{% block content %}
<div class="toolbars space-after">
<div class="toolbar">
<div class="group">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in our toolbars wiki page, single buttons in a toolbar don't need to be wrapped by the .group element anymore. Apply this to the rest of your templates as well! We currently have some (quite many actually) templates in Indico that still use the .group element even if it includes 1 button, but we'll remove them eventually. We just gotta make sure that any new code doesn't increase the amount of code we need to change!

data-title="{{ contrib.title }}">
<td class="i-table id-column">
<span class="vertical-aligner">
<input type="checkbox" class="select-row" name="contribution_id"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from the class and id attributes, i'd put the rest in a new line each, similar to the way you did it in lines 44-46. Same applies for the data-searchable and data-text below and in general anywhere where the list of attributes needs to wrap.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a strong opinion but I would definitely not put type on a new line since it's the most relevant attribute on an <input> tag.

@nop33 nop33 removed their assignment Dec 9, 2016
<div class="group">
<a href="#" class="i-button icon-checkmark js-enable-if-checked disabled"
data-href="#">
{%- trans %}Accept{% endtrans -%}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd group the accept, reject and to be corrected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move them into a dropdown

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it but wasn't sure about the button label: Mark as, Change state? Suggestions are welcome.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if sending papers back for corrections make sense... Shouldn't we enforce leaving some feedback for the submitter?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment field should become mandatory in that case.

</a>
</div>
<div class="group">
<a href="#" class="i-button icon-quill js-enable-if-checked disabled"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the quill icon. Maybe edit would be better? We use the quill in a complete different context on Indico...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

icon-undo maybe? 😕

<a class="i-button icon-checkbox-checked arrow js-dropdown" data-toggle="dropdown"></a>
<ul class="dropdown">
<li>
<a href="#" data-select-all="#assignment-list input:checkbox">{% trans %}All{% endtrans %}</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selecting a row doesn't highlight it. Make sure the handleRowSelection method is executed (is should be executed by calling setupListGenerator as we do in the setupContributionList function of the contribution list (contributions/templates/management/contributions.html)

<ul class="dropdown">
<li><a href="#">{% trans %}Judge{% endtrans %}</a></li>
<li><a href="#">{% trans %}Content reviewer{% endtrans %}</a></li>
<li><a href="#">{% trans %}Layout reviewer{% endtrans %}</a></li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content and layout reviewer options should be available only if the setting is enabled.

</div>
<div class="toolbar">
<div class="group" id="filter-statistics">
{{ render_displayed_entries_fragment(contribs|length, total_entries) }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did the denominator go? 😄
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention that is WIP, my bad. I'm currently working on the list generator that will solve it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just tends to infinity.

</div>
<div class="group">
<span class="i-button label icon-search"></span>
<input type="text" id="search-input" placeholder="{% trans %}Enter #id or search string{% endtrans %}">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The live search is not functional.

</div>
<div class="group">
<a class="i-button arrow js-dropdown" data-toggle="dropdown">
{%- trans %}Assign{% endtrans -%}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Assign and Unassign buttons should be disabled unless there are checked rows. Use:
js-enable-if-checked disabled

placeholder: '#filter-placeholder'
};

$('.list-section [data-toggle=dropdown]').closest('.group').dropdown();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

js-dropdown doesn't work?

"""Assign contrubutions to reviewers and judges"""

def _process(self):
contribs = sorted(self.event_new.contributions, key=lambda x: x.friendly_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key=attrgetter('friendly_id')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you could do that in the Jinja template. event.contributions|sort(attribute='friendly_id')


{% block description %}
{%- trans -%}
Assign <strong>judges</strong>, <strong>content reviewers</strong> and <strong>layout reviewers</strong>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

judges and reviewers to avoid having to use conditionals depending on what's enabled (for such conditionals you'd need to repeat the whole sentence since you cannot have them inside trans blocks)

</div>
<div class="group">
<button class="i-button icon-settings js-dialog-action js-customize-list highlight"
data-href="#"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is WIP?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, forgot to mention in the PR title. I just worked on the table basic structure so far.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave {# TODO: ... #} commets not to forget. It is ok to commit those into devel in early stages of a new release when the blueprint/page is still missing.

<div class="group">
<button class="i-button icon-settings js-dialog-action js-customize-list highlight"
data-href="#"
data-title="{% trans %}Paper assignment list configuration{% endtrans %}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just "Customize list" or something like that? The title doesn't need to be super verbose

<div class="group">
<a href="#" class="i-button icon-checkmark js-enable-if-checked disabled"
data-href="#">
{%- trans %}Accept{% endtrans -%}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move them into a dropdown

@mvidalgarcia mvidalgarcia changed the title Paper assignment page WIP Paper assignment page Dec 12, 2016
</table>
</form>
{%- else %}
{%- call message_box('info') %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this to be the first block. This helps see more clearly the implications of the if block.

{% if not contribs %}
    {%- call message_box('info') %}
    ...
{% else %}
    <form method="POST">
    ...
{% endif %}

{% for contrib in contribs %}
{% set last_revision_state %}
{% if contrib.paper_revisions %}
{{ contrib.paper_revisions.0.state.title }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThiefMaster, muy importante.

</thead>
<tbody>
{% for contrib in contribs %}
{% set last_revision_state %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to start using set blocks with logic inside... Opinions?

Another way to write this would be:

{% if contrib.paper_revisions %}
    {% set last_revision_state = contrib.paper_revisions.0.state.title %}
{% else %}
    {% set last_revision_state %}
        {%- trans %}Paper not yet submitted{% endtrans -%}
    {% endset %}
{% endif %}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd avoid set blocks except where useful. If there's lots of logic inside it might be better suited in a macro.

data-title="{{ contrib.title }}">
<td class="i-table id-column">
<span class="vertical-aligner">
<input type="checkbox" class="select-row" name="contribution_id"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a strong opinion but I would definitely not put type on a new line since it's the most relevant attribute on an <input> tag.

{% from 'events/management/_lists.html' import render_displayed_entries_fragment %}

{% block title %}
{% trans %}Paper Assignment{% endtrans %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title should be the same in all paper-related pages. In this case, Call for Papers I believe.
This we can move to the subtitle block.

</div>
<div class="group">
<button class="i-button icon-settings js-dialog-action js-customize-list highlight"
data-href="#"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave {# TODO: ... #} commets not to forget. It is ok to commit those into devel in early stages of a new release when the blueprint/page is still missing.

</a>
</div>
<div class="group">
<a href="#" class="i-button icon-quill js-enable-if-checked disabled"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

icon-undo maybe? 😕

</div>
<div class="toolbar">
<div class="group" id="filter-statistics">
{{ render_displayed_entries_fragment(contribs|length, total_entries) }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just tends to infinity.

<div class="group">
<a href="#" class="i-button icon-checkmark js-enable-if-checked disabled"
data-href="#">
{%- trans %}Accept{% endtrans -%}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if sending papers back for corrections make sense... Shouldn't we enforce leaving some feedback for the submitter?

@@ -36,6 +36,9 @@
methods=('GET', 'POST'))
_bp.add_url_rule('/manage/papers/enable/<any(content,layout):reviewing_type>', 'switch',
management.RHSwitchReviewingType, methods=('PUT', 'DELETE'))
_bp.add_url_rule('/manage/papers/assignment-list', 'assignment', management.RHPapersAssignmentList)
_bp.add_url_rule('/manage/papers/assign/customize', 'customize_assignment_list', management.RHAssignmentListCustomize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use /manage/papers/assignment-list/customize here and in the line above /manage/papers/assignment-list/ (slash at the end)


from collections import OrderedDict
from operator import attrgetter
from flask import request
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flask < operator

from indico.modules.events.papers.models.revisions import PaperRevisionState, PaperRevision
from indico.modules.events.util import ListGeneratorBase
from indico.web.flask.templating import get_template_module
from indico.util.i18n import _
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

util < web

super(PaperAssignmentListGenerator, self).__init__(event)
self.default_list_config = {
'items': ('state', ),
'filters': {'items': {}}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.default_list_config = {
    'items': ('state', ),
    'filters': {'items': {}}
}

'items': ('state', ),
'filters': {'items': {}}}

state_not_submitted = {None: 'Not yet submitted'}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add translations everywhere: _('Not yet submitted')

"""Render the contribution list template components.

:return: dict containing the list's entries, the fragment of
displayed entries and whether the contrib passed is displayed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...whether the contribution...", it's docstring, no need for abbreviations!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, I'd change it also in the contribution list files as well ;)

{% block description %}
{%- trans -%}
Assign <strong>judges</strong> and <strong>reviewers</strong> to contributions in order to allow assessing
its paper revisions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its or theirs? I am not sure which one fits the best.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of them 😄, I think their fits better

data-dialog-classes="list-filter-dialog"
data-update='{"html": "#assignment-list", "filter_statistics": "#filter-statistics"}'
data-ajax-dialog>
{% trans %}Customize list{% endtrans %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{%- trans %}Customize list{% endtrans -%}

<div class="section">
<div class="icon icon-wrench"></div>
<div class="text">
<div class="label">Customize paper asssignment list</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{% trans %}

from __future__ import unicode_literals

from collections import OrderedDict
from flask import request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flask and sqlalchemy are not stdlib

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(he means they should be in a separate block)

uselist=False,
lazy=True,
viewonly=True,
primaryjoin=((PaperRevision.contribution_id == cls.id) &
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use db.and_() instead of & - more readable IMO when wrapped

@@ -332,6 +332,21 @@ def __table_args__(cls):
)
)

@declared_attr
def paper_last_revision(cls):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

latest_paper_revision or current_paper_revision?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on IRC, paper_last_revision has the upside of namespacing things, which is quite useful to people who (like me) use auto-complete on indico shell.

'session': Contribution.session_id,
'type': Contribution.type_id}
for key, column in filter_cols.iteritems():
ids = set(filters['items'].get(key, ()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the , () is not needed since you check for falsiness in the next line anyway, so the default None is fine

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set(None) -> 'NoneType' object is not iterable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, didn't spot the set() around it

{% from 'message_box.html' import message_box %}

{% macro render_paper_assignment_list(event, total_entries, contribs, static_columns) %}
{% set tz = event.display_tzinfo %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused. also, management wouldn't use display_tzinfo but just tzinfo

<span class="vertical-aligner">
<input type="checkbox" class="select-row"
name="contribution_id"
value="{{ contrib.id }}">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fits in the previous line

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I've changed it because of #2756 (comment)

</span>
</td>
<td class="i-table person-row-cell"
data-searchable="{{ contrib.paper_judges|map(attribute='name')|join(', ')|lower }}">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

|join(', ', attribute='name') - no need for the separate |map()

http://jinja.pocoo.org/docs/dev/templates/#join

<li>
<input type="checkbox" name="field_{{ item_id }}" value="{{ value }}"
id="field_{{ item_id }}_option_{{ value }}"
{% if value|string in filters[item_id]|string %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{{ 'checked' if value|string in filters[item_id] }}?

Also, filters[item_id]|string looks very wrong to me. Are you by any chance converting a list/set to a string and then check whether another string is in it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is when the value is None (in cases like "Not yet submitted", "No track", etc.), then the check is if "None" in [None, ...] which is false and must be true.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like we should find a better solution then.

{% set value = none if value is none else value|string %}

How about that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that works! 👍

</div>
</div>
</div>
<div class="success-message-box js-clear-filters-message" style="display: none">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none;

def _build_query(self):
return (Contribution.query.with_parent(self.event)
.order_by(Contribution.friendly_id)
.options(subqueryload('paper_last_revision')))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It almost looks easy now. :trollface:

(PaperRevision.submitted_dt == (db.select([db.func.max(PaperRevision.submitted_dt)])
.where(PaperRevision.contribution_id == cls.id)
.correlate_except(PaperRevision)
.as_scalar()))))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation seems wrong.

@mvidalgarcia mvidalgarcia force-pushed the paper-assignment-page branch 2 times, most recently from ac458b7 to 0d6983d Compare December 16, 2016 16:06
lazy=True,
viewonly=True,
primaryjoin=(db.and_((PaperRevision.contribution_id == cls.id),
(PaperRevision.submitted_dt == (db.select([db.func.max(PaperRevision.submitted_dt)])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assign the subquery to a subquery variable and use PaperRevision.submitted_dt == subquery.as_scalar() here (or even move the as_scalar() to the subquery = ... too)

uselist=False,
lazy=True,
viewonly=True,
primaryjoin=(db.and_((PaperRevision.contribution_id == cls.id),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the innermost () now; they were only needed because of the precedence of &

@@ -22,6 +22,7 @@
from indico.modules.events.papers.forms import PaperTeamsForm, make_competences_form
from indico.modules.events.papers.operations import (set_reviewing_state, update_team_members, create_competences,
update_competences)
from indico.modules.events.papers.lists import PaperAssignmentListGenerator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lists < operations

@@ -122,7 +122,7 @@ def render_list(self, contrib=None):
:param contrib: Used in RHs responsible for CRUD operations on a
contribution.
:return: dict containing the list's entries, the fragment of
displayed entries and whether the contrib passed is displayed
displayed entries and whether the contribution passed is displayed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstrings should wrap after 80 characters and python code after 120. Make sure you setup your editor to indicate that 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def __init__(self, event):
super(PaperAssignmentListGenerator, self).__init__(event)
self.default_list_config = {
'items': ('state', ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space after 'state',

@@ -39,6 +39,8 @@
_bp.add_url_rule('/manage/papers/assignment-list/', 'assignment', management.RHPapersAssignmentList)
_bp.add_url_rule('/manage/papers/assignment-list/customize', 'customize_assignment_list',
management.RHAssignmentListCustomize, methods=('GET', 'POST'))
_bp.add_url_rule('/manage/papers/assignment-list/change-state', 'manage_papers_state',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we call this "judging" in the abstracts module (RH name, URL, endpoint name, etc)? In that case I'd use similar naming here for consistency.


def _process(self):
form = BulkPaperJudgmentForm(event=self.event_new, judgment=request.form.get('judgment'),
contribution_id=[a.id for a in self.contributions])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied from abstracts I guess? ;)

a doesn't fit here much, I'd use c or the generic x (but usually I go for c for contributions)

@@ -57,3 +61,21 @@ def update_competences(user_competences, competences):
event.log(EventLogRealm.management, EventLogKind.positive, 'Papers',
"Updated competences for user {}".format(user_competences.user.full_name), session.user,
data={'Competences': ', '.join(competences)})


def paper_change_state(contribution, contrib_data, judgment, judge, send_notifications=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

judge_paper?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just clarifying, the rationale is to use verbs for functions/methods as much as possible.

num_judged_contribs = len(submitted_contributions)
num_prejudged_contribs = len(self.contributions) - num_judged_contribs
if num_judged_contribs:
flash(ngettext("One paper contribution has been judged.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just "paper" or "contribution's paper" - "paper contribution" sounds rather weird.

if kwargs['judgment']:
self._remove_unused_fields(kwargs['judgment'])

def _remove_unused_fields(self, judgment):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can go away if we don't have any fields that are specific to certain judgment actions.



def paper_change_state(contribution, contrib_data, judgment, judge, send_notifications=False):
log_data = {'New state': orig_string(judgment.title)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move that down so all the logging stuff is at the end

contribution.paper_last_revision.state = PaperRevisionState.rejected
elif judgment == PaperAction.to_be_corrected:
contribution.paper_last_revision.state = PaperRevisionState.to_be_corrected
PaperReviewComment(paper_revision=contribution.paper_last_revision, user=judge,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we do want to save the judgment comment as a normal comment in the end and not in a separate field on the revision?

Anyway, while this works (due to being added to the SA session since you link it to he prevision) I think it's slighly ugly to create an instance without using it anywhere. I'd rather do it like this:

if contrib_data['judgment_comment']:
    comment = PaperReviewComment(user=judge, text=contrib_data['judgment_comment'])
    contribution.paper_last_revision.comments.append(comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought we settled for adding the judgment comment as a field in the revision. Not that I disagree with this approach, but just wondering if I missed something.

log_data['Sent notifications'] = send_notifications
if send_notifications:
pass # TODO: manage notifications
logger.info('Paper contribution %s changed state by %s', contribution.title, judge)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%r for the second one. I'd also include the new state.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like before, "paper contribution" sounds really strange.

@@ -57,3 +61,21 @@ def update_competences(user_competences, competences):
event.log(EventLogRealm.management, EventLogKind.positive, 'Papers',
"Updated competences for user {}".format(user_competences.user.full_name), session.user,
data={'Competences': ', '.join(competences)})


def paper_change_state(contribution, contrib_data, judgment, judge, send_notifications=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just clarifying, the rationale is to use verbs for functions/methods as much as possible.

judgment_data, contrib_data = form.split_data
# TODO: For now, I'm considering that any submitted paper contribution can change
# its state (even rejected ones)
submitted_contributions = [c for c in self.contributions if c.paper_last_revision]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually how many papers have been submitted. Why not num_papers?

submitted_contributions = [c for c in self.contributions if c.paper_last_revision]
for contrib in submitted_contributions:
paper_change_state(contrib, contrib_data, judge=session.user, **judgment_data)
num_judged_contribs = len(submitted_contributions)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the papers that are judged, not the contributions. I would name these num_judged_papers.

for contrib in submitted_contributions:
paper_change_state(contrib, contrib_data, judge=session.user, **judgment_data)
num_judged_contribs = len(submitted_contributions)
num_prejudged_contribs = len(self.contributions) - num_judged_contribs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this has anything to do with the paper having been prejudged. Rather, it's simply contributions that haven't received a paper submission. What about renaming the variable num_missing_paper?

contribution.paper_last_revision.state = PaperRevisionState.rejected
elif judgment == PaperAction.to_be_corrected:
contribution.paper_last_revision.state = PaperRevisionState.to_be_corrected
PaperReviewComment(paper_revision=contribution.paper_last_revision, user=judge,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought we settled for adding the judgment comment as a field in the revision. Not that I disagree with this approach, but just wondering if I missed something.

@@ -99,8 +98,7 @@ def judge_paper(contribution, contrib_data, judgment, judge, send_notifications=
elif judgment == PaperAction.to_be_corrected:
contribution.paper_last_revision.state = PaperRevisionState.to_be_corrected
if contrib_data['judgment_comment']:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this check is needed - assigning an empty comment does no harm

@@ -15,7 +15,26 @@
* along with Indico; if not, see <http://www.gnu.org/licenses/>.
*/

(function() {
/* global setupListGenerator:false, applySearchFilters:false, setupTableSorter: false */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no space after the last : for consistency


@no_autoflush
def judge_paper(contribution, contrib_data, judgment, judge, send_notifications=False):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there shouldn't be an empty line here

contribution.paper_last_revision.state = PaperRevisionState.rejected
elif judgment == PaperAction.to_be_corrected:
contribution.paper_last_revision.state = PaperRevisionState.to_be_corrected
if contrib_data['judgment_comment']:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can always set the comment. that way judging it again (even though this shouldn't happen) would properly overwrite an existing comment

logger.info('Paper %s changed state by %r to %s', contribution.title, judge,
orig_string(judgment.title))
contribution.event_new.log(EventLogRealm.management, EventLogKind.change, 'Papers',
'Paper "{}" changed state'.format(contribution.title), judge, data=log_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

".. was judged .." and I'd include the friendly id in this log message and similar ones: Paper #123 ("foo") was judged...

Might be a good idea to add this property to Contribution (we also have it in Abstract) to make it easier/cleaner:

    @property
    def verbose_title(self):
        return '#{} ({})'.format(self.friendly_id, self.title)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use orig_string() here, too. we don't want translated messages in logs

log_data = {'New state': orig_string(judgment.title), 'Sent notifications': send_notifications}
if send_notifications:
pass # TODO: manage notifications
logger.info('Paper %s changed state by %r to %s', contribution.title, judge,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

".. was judged .."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Paper %r .. and use contribution instead of contribution.title.
This is for the logfile, having the repr is much more useful there than just the title

@OmeGak OmeGak changed the title WIP Paper assignment page Paper assignment page Jan 11, 2017
session_empty = {None: _('No session')}
type_empty = {None: _('No type')}
state_choices = {state.value: state.title for state in PaperRevisionState}
track_choices = OrderedDict((unicode(t.id), t.title) for t in sorted(self.event.tracks,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why do we need to unicode the IDs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most likely it goes through json encoding at some point and JSON only supports string keys

@OmeGak OmeGak merged commit 69b2875 into indico:devel Jan 11, 2017
@mvidalgarcia mvidalgarcia deleted the paper-assignment-page branch January 12, 2017 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants