コード例 #1
0
ファイル: timeline.py プロジェクト: arky/pootle
 def context(self):
     return dict(
         value=format_html(
             u"{} <span class='timeline-arrow'></span> {}",
             STATES_MAP[int(to_python(self.submission.old_value))],
             STATES_MAP[int(to_python(self.submission.new_value))]),
         state=True)
コード例 #2
0
 def state_change_entry(self):
     entry = self.entry_dict
     entry['old_value'] = STATES_MAP[int(
         to_python(self.submission.old_value))]
     entry['new_value'] = STATES_MAP[int(
         to_python(self.submission.new_value))]
     return entry
コード例 #3
0
def _get_state_changed_value(submission):
    params = {
        'old_value': STATES_MAP[int(to_python(submission.old_value))],
        'new_value': STATES_MAP[int(to_python(submission.new_value))]
    }
    return (u"%(old_value)s "
            u"<span class='timeline-arrow'></span> "
            u"%(new_value)s" % params)
コード例 #4
0
ファイル: timeline.py プロジェクト: arky/pootle
def _get_state_changed_value(submission):
    params = {
        'old_value': STATES_MAP[int(to_python(submission.old_value))],
        'new_value': STATES_MAP[int(to_python(submission.new_value))]}
    return (
        u"%(old_value)s "
        u"<span class='timeline-arrow'></span> "
        u"%(new_value)s" % params)
コード例 #5
0
ファイル: views.py プロジェクト: andynicholson/pootle
def get_history(request, unit):
    """
    @return: JSON with changes to the unit rendered in HTML.
    """
    entries = Submission.objects.filter(unit=unit, field="pootle_store.Unit.target")
    entries = entries.select_related("submitter__user", "translation_project__language")
    #: list of tuples (datetime, submitter, value)
    values = []

    import locale
    from pootle_store.fields import to_python

    old_value = u""
    language = None

    for entry in entries:
        language = entry.translation_project.language
        # If the old_value doesn't correspond to the previous new_value, let's
        # add it anyway, even if we don't have more information about it. It
        # might be because of an upload, VCS action, etc. that wasn't recorded.
        if old_value != entry.old_value:
            # Translators: this refers to an unknown date
            values.append((_("(unknown)"), u"", to_python(entry.old_value)))
        old_value = entry.new_value
        values.append((
                entry.creation_time.strftime(locale.nl_langinfo(locale.D_T_FMT)),
                entry.submitter,
                to_python(old_value),
        ))

    if old_value and old_value != unit.target:
        values.append((_("Now"), u"", to_python(old_value)))

    # let's reverse the chronological order
    values.reverse()
    ec = {
        'values': values,
        'language': language,
    }

    if request.is_ajax():
        t = loader.get_template('unit/history-xhr.html')
        c = RequestContext(request, ec)
        json = {
                # The client will want to confirm that the response is
                # relevant for the unit on screen at the time of receiving
                # this, so we add the uid.
                'uid': unit.id,
                'entries': t.render(c),
        }
        response = simplejson.dumps(json)
        return HttpResponse(response, mimetype="application/json")
    else:
        return render_to_response(
                'unit/history.html',
                ec,
                context_instance=RequestContext(request),
        )
コード例 #6
0
ファイル: proxy.py プロジェクト: unasettimana/pootle
    def translation_action_type(self):
        if not self.unit:
            return
        if self.type not in SubmissionTypes.EDIT_TYPES:
            return
        if self.field == SubmissionFields.STATE:
            # Note that a submission where field is STATE
            # should be created before a submission where
            # field is TARGET
            state = int(to_python(self.new_value))
            if state == TRANSLATED:
                return TranslationActionTypes.REVIEWED
            elif state == FUZZY:
                return TranslationActionTypes.NEEDS_WORK
        if self.field != SubmissionFields.TARGET:
            return
        if self.new_value == '':
            return TranslationActionTypes.REMOVED
        # Note that we analyze current unit state:
        # if this submission is not last unit state
        # can be changed
        if self.unit_state not in [TRANSLATED, FUZZY]:
            return

        if self.old_value != '':
            return TranslationActionTypes.EDITED

        return (TranslationActionTypes.PRE_TRANSLATED if self.unit_state
                == FUZZY else TranslationActionTypes.TRANSLATED)
コード例 #7
0
def unit_source_update(counter, unit_source):
    unit_source.source_hash = md5(force_bytes(
        unit_source.unit.source_f)).hexdigest()
    unit_source.source_length = len(unit_source.unit.source_f)
    unit_source.source_wordcount = max(
        1, (counter.count_words(to_python(unit_source.unit.source_f)) or 0))
    return unit_source
コード例 #8
0
ファイル: proxy.py プロジェクト: phlax/pootle
    def translation_action_type(self):
        if not self.unit:
            return
        if self.type not in SubmissionTypes.EDIT_TYPES:
            return
        if self.field == SubmissionFields.STATE:
            # Note that a submission where field is STATE
            # should be created before a submission where
            # field is TARGET
            state = int(to_python(self.new_value))
            if state == TRANSLATED:
                return TranslationActionTypes.REVIEWED
            elif state == FUZZY:
                return TranslationActionTypes.NEEDS_WORK
        if self.field != SubmissionFields.TARGET:
            return
        if self.new_value == '':
            return TranslationActionTypes.REMOVED
        # Note that we analyze current unit state:
        # if this submission is not last unit state
        # can be changed
        if self.unit_state not in [TRANSLATED, FUZZY]:
            return

        if self.old_value != '':
            return TranslationActionTypes.EDITED

        return (
            TranslationActionTypes.PRE_TRANSLATED
            if self.unit_state == FUZZY
            else TranslationActionTypes.TRANSLATED)
コード例 #9
0
def unit_source_update(counter, unit_source):
    unit_source.source_hash = md5(
        force_bytes(unit_source.unit.source_f)).hexdigest()
    unit_source.source_length = len(unit_source.unit.source_f)
    unit_source.source_wordcount = max(
        1, (counter.count_words(to_python(unit_source.unit.source_f)) or 0))
    return unit_source
コード例 #10
0
ファイル: models.py プロジェクト: saily/pootle
    def get_submission_message(self):
        """Returns a message describing the submission.

        The message includes the user (with link to profile and gravatar), a
        message describing the action performed, and when it was performed.
        """
        unit = {}
        source = {}

        if self.unit is not None:
            unit = {
                'source': escape(truncatechars(self.unit, 50)),
                'url': self.unit.get_translate_url(),
            }
            source = {
                'source_string': '<i><a href="%(url)s">%(source)s</a></i>' %
                    unit,
            }

            if self.quality_check is not None:
                check_name = self.quality_check.name
                unit.update({
                    'check_name': check_name,
                    'check_display_name': check_names.get(check_name, check_name),
                    'checks_url': reverse('pootle-checks-descriptions'),
                })
                source.update({
                    'check_name': '<a href="%(checks_url)s#%(check_name)s">'
                                  '%(check_display_name)s</a>' % unit,
                })

        if (self.suggestion and
            self.type in (SubmissionTypes.SUGG_ACCEPT, SubmissionTypes.SUGG_REJECT)):
            displayuser = self.suggestion.reviewer
        else:
            # Sadly we may not have submitter information in all the
            # situations yet
            # TODO check if it is true
            if self.submitter:
                displayuser = self.submitter
            else:
                User = get_user_model()
                displayuser = User.objects.get_nobody_user()

        action_bundle = {
            "profile_url": displayuser.get_absolute_url(),
            "gravatar_url": displayuser.gravatar_url(20),
            "displayname": escape(displayuser.display_name),
            "username": displayuser.username,
            "display_datetime": dateformat.format(self.creation_time),
            "iso_datetime": self.creation_time.isoformat(),
            "action": "",
        }

        msg = {
            SubmissionTypes.REVERT: _(
                'reverted translation for %(source_string)s',
                source
            ),
            SubmissionTypes.SUGG_ACCEPT: _(
                'accepted suggestion for %(source_string)s',
                source
            ),
            SubmissionTypes.SUGG_ADD: _(
                'added suggestion for %(source_string)s',
                source
            ),
            SubmissionTypes.SUGG_REJECT: _(
                'rejected suggestion for %(source_string)s',
                source
            ),
            SubmissionTypes.UPLOAD: _(
                'uploaded a file'
            ),
            SubmissionTypes.MUTE_CHECK: _(
                'muted %(check_name)s for %(source_string)s',
                source
            ),
            SubmissionTypes.UNMUTE_CHECK: _(
                'unmuted %(check_name)s for %(source_string)s',
                source
            ),
        }.get(self.type, None)

        #TODO Look how to detect submissions for "sent suggestion", "rejected
        # suggestion"...

        #TODO Fix bug 3011 and replace the following code with the appropiate
        # one in the dictionary above.

        if msg is None:
            try:
                if self.field == SubmissionFields.TARGET:
                    if self.new_value != '':
                        # Note that we analyze current unit state:
                        # if this submission is not last unit state
                        # can be changed
                        if self.unit.state == TRANSLATED:
                            if self.old_value == '':
                                msg = _('translated %(source_string)s', source)
                            else:
                                msg = _('edited %(source_string)s', source)
                        elif self.unit.state == FUZZY:
                            if self.old_value == '':
                                msg = _('pre-translated %(source_string)s',
                                        source)
                            else:
                                msg = _('edited %(source_string)s', source)
                    else:
                        msg = _('removed translation for %(source_string)s',
                                source)
                elif self.field == SubmissionFields.STATE:
                    # Note that a submission where field is STATE
                    # should be created before a submission where
                    # field is TARGET
                    msg = {
                        TRANSLATED: _('reviewed %(source_string)s', source),
                        FUZZY: _('marked as needs work %(source_string)s', source)
                    }.get(int(to_python(self.new_value)), '')
                else:
                    msg = _('unknown action %(source_string)s', source)
            except AttributeError:
                return ''

        action_bundle['action'] = msg

        return mark_safe(
            u'<div class="last-action">'
            '  <a href="%(profile_url)s">'
            '    <img src="%(gravatar_url)s" />'
            '    <span title="%(username)s">%(displayname)s</span>'
            '  </a>'
            '  <span class="action-text">%(action)s</span>'
            '  <time class="extra-item-meta js-relative-date"'
            '    title="%(display_datetime)s" datetime="%(iso_datetime)s">&nbsp;'
            '  </time>'
            '</div>'
            % action_bundle)
コード例 #11
0
def _calculate_timeline(request, unit):
    submission_filter = (Q(field__in=[
        SubmissionFields.TARGET, SubmissionFields.STATE,
        SubmissionFields.COMMENT, SubmissionFields.NONE
    ])
                         | Q(type__in=SubmissionTypes.SUGGESTION_TYPES))
    timeline = (Submission.objects.filter(
        unit=unit).filter(submission_filter).exclude(
            field=SubmissionFields.COMMENT,
            creation_time=unit.commented_on).order_by("id"))
    User = get_user_model()
    entries_group = []
    context = {}
    timeline_fields = [
        "type", "old_value", "new_value", "submitter_id", "creation_time",
        "translation_project__language__code", "field", "suggestion_id",
        "suggestion__target_f", "quality_check__name", "submitter__username",
        "submitter__full_name", "suggestion__user__full_name",
        "submitter__email", "suggestion__user__username"
    ]

    grouped_timeline = groupby(timeline.values(*timeline_fields),
                               key=lambda item: "\001".join([
                                   str(x) for x in [
                                       item['submitter_id'],
                                       item['creation_time'],
                                       item['suggestion_id'],
                                   ]
                               ]))

    # Group by submitter id and creation_time because
    # different submissions can have same creation time
    for key_, values in grouped_timeline:
        entry_group = {
            'entries': [],
        }

        for item in values:
            # Only add creation_time information for the whole entry group once
            entry_group['datetime'] = item['creation_time']

            # Only add submitter information for the whole entry group once
            entry_group.setdefault('submitter', ProxyTimelineUser(item))

            context.setdefault(
                'language',
                ProxyTimelineLanguage(
                    item['translation_project__language__code']))

            entry = {
                'field': item['field'],
                'field_name':
                SubmissionFields.NAMES_MAP.get(item['field'], None),
                'type': item['type']
            }
            if item['field'] == SubmissionFields.STATE:
                entry['old_value'] = STATES_MAP[int(
                    to_python(item['old_value']))]
                entry['new_value'] = STATES_MAP[int(
                    to_python(item['new_value']))]
            elif item['suggestion_id']:
                entry.update({
                    'suggestion_text':
                    item['suggestion__target_f'],
                    'suggestion_description':
                    mark_safe(_get_suggestion_description(item))
                })
            elif item['quality_check__name']:
                check_name = item['quality_check__name']
                check_url = (u''.join(
                    [reverse('pootle-checks-descriptions'), '#', check_name]))
                entry.update({
                    'check_name': check_name,
                    'check_display_name': check_names[check_name],
                    'checks_url': check_url
                })
            else:
                entry['new_value'] = to_python(item['new_value'])

            entry_group['entries'].append(entry)

        entries_group.append(entry_group)

    has_creation_entry = (len(entries_group) > 0 and
                          entries_group[0]['datetime'] == unit.creation_time)
    if (has_creation_entry):
        entries_group[0]['created'] = True
    else:
        created = {
            'created': True,
            'submitter': User.objects.get_system_user()
        }

        if unit.creation_time:
            created['datetime'] = unit.creation_time
        entries_group[:0] = [created]

    # Let's reverse the chronological order
    entries_group.reverse()
    context['entries_group'] = entries_group
    t = loader.get_template('editor/units/xhr_timeline.html')
    return t.render(context, request)
コード例 #12
0
ファイル: timeline.py プロジェクト: AlfredWei/pootle
def _calculate_timeline(request, unit):
    submission_filter = (
        Q(field__in=[SubmissionFields.TARGET, SubmissionFields.STATE,
                     SubmissionFields.COMMENT, SubmissionFields.NONE])
        | Q(type__in=SubmissionTypes.SUGGESTION_TYPES))
    timeline = (
        Submission.objects.filter(unit=unit)
                          .filter(submission_filter)
                          .exclude(field=SubmissionFields.COMMENT,
                                   creation_time=unit.commented_on)
                          .order_by("id"))
    User = get_user_model()
    entries_group = []
    context = {}
    timeline_fields = [
        "type", "old_value", "new_value", "submitter_id", "creation_time",
        "translation_project__language__code", "field", "suggestion_id",
        "suggestion__target_f", "quality_check__name", "submitter__username",
        "submitter__full_name", "suggestion__user__full_name", "submitter__email",
        "suggestion__user__username"]

    grouped_timeline = groupby(
        timeline.values(*timeline_fields),
        key=lambda x: ("%d\001%s" % (x['submitter_id'], x['creation_time'])))

    # Group by submitter id and creation_time because
    # different submissions can have same creation time
    for key, values in grouped_timeline:
        entry_group = {
            'entries': [],
        }

        for item in values:
            # Only add creation_time information for the whole entry group once
            entry_group['datetime'] = item['creation_time']

            # Only add submitter information for the whole entry group once
            entry_group.setdefault('submitter', ProxyTimelineUser(item))

            context.setdefault(
                'language',
                ProxyTimelineLanguage(item['translation_project__language__code']))

            entry = {
                'field': item['field'],
                'field_name': SubmissionFields.NAMES_MAP.get(item['field'], None),
                'type': item['type']}
            if item['field'] == SubmissionFields.STATE:
                entry['old_value'] = STATES_MAP[int(to_python(item['old_value']))]
                entry['new_value'] = STATES_MAP[int(to_python(item['new_value']))]
            elif item['suggestion_id']:
                entry.update({
                    'suggestion_text': item['suggestion__target_f'],
                    'suggestion_description':
                        mark_safe(_get_suggestion_description(item))})
            elif item['quality_check__name']:
                check_name = item['quality_check__name']
                check_url = (
                    u''.join(
                        [reverse('pootle-checks-descriptions'),
                         '#', check_name]))
                entry.update({
                    'check_name': check_name,
                    'check_display_name': check_names[check_name],
                    'checks_url': check_url})
            else:
                entry['new_value'] = to_python(item['new_value'])

            entry_group['entries'].append(entry)

        entries_group.append(entry_group)

    has_creation_entry = (
        len(entries_group) > 0
        and entries_group[0]['datetime'] == unit.creation_time)
    if (has_creation_entry):
        entries_group[0]['created'] = True
    else:
        created = {
            'created': True,
            'submitter': User.objects.get_system_user()}

        if unit.creation_time:
            created['datetime'] = unit.creation_time
        entries_group[:0] = [created]

    # Let's reverse the chronological order
    entries_group.reverse()
    context['entries_group'] = entries_group
    t = loader.get_template('editor/units/xhr_timeline.html')
    c = RequestContext(request, context)
    return t.render(c).replace('\n', '')
コード例 #13
0
 def base_entry(self):
     entry = self.entry_dict
     entry['new_value'] = to_python(self.submission.new_value)
     return entry
コード例 #14
0
ファイル: models.py プロジェクト: egr-kittner/pootle
    def get_submission_info(self):
        """Returns a dictionary describing the submission.

        The dict includes the user (with link to profile and gravatar),
        a type and translation_action_type describing the action performed,
        and when it was performed.
        """
        result = {}

        if self.unit is not None:
            result.update({
                'unit_source': truncatechars(self.unit, 50),
                'unit_url': self.unit.get_translate_url(),
            })

            if self.quality_check is not None:
                check_name = self.quality_check.name
                result.update({
                    'check_name': check_name,
                    'check_display_name': check_names.get(check_name, check_name),
                    'checks_url': reverse('pootle-checks-descriptions'),
                })

        if (self.suggestion and
            self.type in (SubmissionTypes.SUGG_ACCEPT, SubmissionTypes.SUGG_REJECT)):
            displayuser = self.suggestion.reviewer
        else:
            # Sadly we may not have submitter information in all the
            # situations yet
            # TODO check if it is true
            if self.submitter:
                displayuser = self.submitter
            else:
                User = get_user_model()
                displayuser = User.objects.get_nobody_user()

        result.update({
            "profile_url": displayuser.get_absolute_url(),
            "email": displayuser.email_hash,
            "displayname": displayuser.display_name,
            "username": displayuser.username,
            "display_datetime": dateformat.format(self.creation_time),
            "iso_datetime": self.creation_time.isoformat(),
            "type": self.type,
            "mtime": int(dateformat.format(self.creation_time, 'U')),
        })

        #TODO Fix bug 3011 and remove the following code related
        # to TranslationActionTypes.

        if self.type in SubmissionTypes.EDIT_TYPES:
            translation_action_type = None
            try:
                if self.field == SubmissionFields.TARGET:
                    if self.new_value != '':
                        # Note that we analyze current unit state:
                        # if this submission is not last unit state
                        # can be changed
                        if self.unit.state == TRANSLATED:

                            if self.old_value == '':
                                translation_action_type = \
                                    TranslationActionTypes.TRANSLATED
                            else:
                                translation_action_type = \
                                    TranslationActionTypes.EDITED
                        elif self.unit.state == FUZZY:
                            if self.old_value == '':
                                translation_action_type = \
                                    TranslationActionTypes.PRE_TRANSLATED
                            else:
                                translation_action_type = \
                                    TranslationActionTypes.EDITED
                    else:
                        translation_action_type = TranslationActionTypes.REMOVED
                elif self.field == SubmissionFields.STATE:
                    # Note that a submission where field is STATE
                    # should be created before a submission where
                    # field is TARGET

                    translation_action_type = {
                        TRANSLATED: TranslationActionTypes.REVIEWED,
                        FUZZY: TranslationActionTypes.NEEDS_WORK
                    }.get(int(to_python(self.new_value)), None)

            except AttributeError:
                return result

            result['translation_action_type'] = translation_action_type

        return result
コード例 #15
0
    def get_submission_message(self):
        """Returns a message describing the submission.

        The message includes the user (with link to profile and gravatar), a
        message describing the action performed, and when it was performed.
        """
        unit = {}
        source = {}

        if self.unit is not None:
            unit = {
                'source': escape(truncatechars(self.unit, 50)),
                'url': self.unit.get_translate_url(),
            }
            source = {
                'source_string':
                '<i><a href="%(url)s">%(source)s</a></i>' % unit,
            }

            if self.check is not None:
                unit.update({
                    'check_name':
                    self.check.name,
                    'check_display_name':
                    check_names[self.check.name],
                    'checks_url':
                    reverse('pootle-staticpages-display',
                            args=['help/quality-checks']),
                })
                source.update({
                    'check_name':
                    '<a href="%(checks_url)s#%(check_name)s">'
                    '%(check_display_name)s</a>' % unit,
                })

        if (self.suggestion and self.type
                in (SubmissionTypes.SUGG_ACCEPT, SubmissionTypes.SUGG_REJECT)):
            displayuser = self.suggestion.reviewer
        else:
            # Sadly we may not have submitter information in all the
            # situations yet
            # TODO check if it is true
            if self.submitter:
                displayuser = self.submitter
            else:
                User = get_user_model()
                displayuser = User.objects.get_nobody_user()

        displayname = displayuser.display_name

        action_bundle = {
            "profile_url": displayuser.get_absolute_url(),
            "gravatar_url": displayuser.gravatar_url(20),
            "displayname": displayname,
            "username": displayuser.username,
            "date": self.creation_time,
            "isoformat_date": self.creation_time.isoformat(),
            "action": "",
        }

        msg = {
            SubmissionTypes.REVERT:
            _('reverted translation for %(source_string)s', source),
            SubmissionTypes.SUGG_ACCEPT:
            _('accepted suggestion for %(source_string)s', source),
            SubmissionTypes.SUGG_ADD:
            _('added suggestion for %(source_string)s', source),
            SubmissionTypes.SUGG_REJECT:
            _('rejected suggestion for %(source_string)s', source),
            SubmissionTypes.UPLOAD:
            _('uploaded a file'),
            SubmissionTypes.MUTE_CHECK:
            _('muted %(check_name)s for %(source_string)s', source),
            SubmissionTypes.UNMUTE_CHECK:
            _('unmmuted %(check_name)s for %(source_string)s', source),
        }.get(self.type, None)

        #TODO Look how to detect submissions for "sent suggestion", "rejected
        # suggestion"...

        #TODO Fix bug 3011 and replace the following code with the appropiate
        # one in the dictionary above.

        if msg is None:
            try:
                if self.field == SubmissionFields.TARGET:
                    if self.new_value != '':
                        # Note that we analyze current unit state:
                        # if this submission is not last unit state
                        # can be changed
                        if self.unit.state == TRANSLATED:
                            if self.old_value == '':
                                msg = _('translated %(source_string)s', source)
                            else:
                                msg = _('edited %(source_string)s', source)
                        elif self.unit.state == FUZZY:
                            if self.old_value == '':
                                msg = _('pre-translated %(source_string)s',
                                        source)
                            else:
                                msg = _('edited %(source_string)s', source)
                    else:
                        msg = _('removed translation for %(source_string)s',
                                source)
                elif self.field == SubmissionFields.STATE:
                    # Note that a submission where field is STATE
                    # should be created before a submission where
                    # field is TARGET
                    msg = {
                        TRANSLATED: _('reviewed %(source_string)s', source),
                        FUZZY: _('marked as fuzzy %(source_string)s', source)
                    }.get(int(to_python(self.new_value)), '')
                else:
                    msg = _('unknown action %(source_string)s', source)
            except AttributeError:
                return ''

        action_bundle['action'] = msg

        return mark_safe(
            u'<div class="last-action">'
            '  <a href="%(profile_url)s">'
            '    <img src="%(gravatar_url)s" />'
            '    <span title="%(username)s">%(displayname)s</span>'
            '  </a>'
            '  <span class="action-text">%(action)s</span>'
            '  <time class="extra-item-meta js-relative-date"'
            '    title="%(date)s" datetime="%(isoformat_date)s">&nbsp;'
            '  </time>'
            '</div>' % action_bundle)
コード例 #16
0
ファイル: timeline.py プロジェクト: ta2-1/pootle
def _calculate_timeline(request, unit):
    submission_filter = (
        Q(field__in=[SubmissionFields.TARGET, SubmissionFields.STATE,
                     SubmissionFields.COMMENT, SubmissionFields.NONE]))
    subs = (
        Submission.objects.filter(unit=unit)
                          .filter(submission_filter))
    if unit.changed and unit.change.commented_on:
        subs = subs.exclude(
            field=SubmissionFields.COMMENT,
            creation_time=unit.commented_on)
    timeline = subs.order_by("id")
    User = get_user_model()
    entries_group = []
    context = {}
    timeline_fields = [
        "type", "old_value", "new_value", "submitter_id", "creation_time",
        "translation_project__language__code", "field", "suggestion_id",
        "suggestion__target_f", "quality_check__name", "submitter__username",
        "submitter__full_name", "suggestion__user__full_name", "submitter__email",
        "suggestion__user__username"]

    grouped_timeline = groupby(
        timeline.values(*timeline_fields),
        key=lambda item: "\001".join([
            str(x) for x in
            [
                item['submitter_id'],
                item['creation_time'],
                item['suggestion_id'],
            ]
        ])
    )

    # Group by submitter id and creation_time because
    # different submissions can have same creation time
    for key_, values in grouped_timeline:
        entry_group = {
            'entries': [],
        }

        for item in values:
            # Only add creation_time information for the whole entry group once
            entry_group['datetime'] = item['creation_time']

            # Only add submitter information for the whole entry group once
            entry_group.setdefault('submitter', ProxyTimelineUser(item))

            context.setdefault(
                'language',
                ProxyTimelineLanguage(item['translation_project__language__code']))

            entry = {
                'field': item['field'],
                'field_name': SubmissionFields.NAMES_MAP.get(item['field'], None),
                'type': item['type']}
            if item['field'] == SubmissionFields.STATE:
                entry['old_value'] = STATES_MAP[int(to_python(item['old_value']))]
                entry['new_value'] = STATES_MAP[int(to_python(item['new_value']))]
            elif item['suggestion_id']:
                entry.update({
                    'suggestion_text': item['suggestion__target_f']})
            elif item['quality_check__name']:
                check_name = item['quality_check__name']
                check_url = (
                    u''.join(
                        [reverse('pootle-checks-descriptions'),
                         '#', check_name]))
                entry.update({
                    'check_name': check_name,
                    'check_display_name': CHECK_NAMES[check_name],
                    'checks_url': check_url})
            else:
                entry['new_value'] = to_python(item['new_value'])

            entry_group['entries'].append(entry)

        entries_group.append(entry_group)

    created = {
        'created': True,
        'submitter': User.objects.get_system_user()}

    if unit.creation_time:
        created['datetime'] = unit.creation_time
    entries_group[:0] = [created]

    # Let's reverse the chronological order
    entries_group.reverse()
    context['entries_group'] = entries_group
    t = loader.get_template('editor/units/xhr_timeline.html')
    return t.render(context=context, request=request)
コード例 #17
0
ファイル: timeline.py プロジェクト: ta2-1/pootle
 def state_change_entry(self):
     entry = self.entry_dict
     entry['old_value'] = STATES_MAP[int(to_python(self.submission.old_value))]
     entry['new_value'] = STATES_MAP[int(to_python(self.submission.new_value))]
     return entry
コード例 #18
0
ファイル: timeline.py プロジェクト: ta2-1/pootle
 def base_entry(self):
     entry = self.entry_dict
     entry['new_value'] = to_python(self.submission.new_value)
     return entry
コード例 #19
0
ファイル: views.py プロジェクト: darkdreamingdan/pootle
def timeline(request, unit):
    """Returns a JSON-encoded string including the changes to the unit
    rendered in HTML.
    """
    timeline = Submission.objects.filter(unit=unit, field__in=[
        SubmissionFields.TARGET, SubmissionFields.STATE,
        SubmissionFields.COMMENT
    ])
    timeline = timeline.select_related("submitter__user",
                                       "translation_project__language")

    context = {}
    entries_group = []

    import locale
    from pootle_store.fields import to_python

    for key, values in groupby(timeline, key=lambda x: x.creation_time):
        entry_group = {
            'datetime': key,
            'datetime_str': key.strftime(locale.nl_langinfo(locale.D_T_FMT)),
            'entries': [],
        }

        for item in values:
            # Only add submitter information for the whole entry group once
            entry_group.setdefault('submitter', item.submitter)

            context.setdefault('language', item.translation_project.language)

            entry = {
                'field': item.field,
                'field_name': SubmissionFields.NAMES_MAP[item.field],
            }

            if item.field == SubmissionFields.STATE:
                entry['old_value'] = STATES_MAP[int(to_python(item.old_value))]
                entry['new_value'] = STATES_MAP[int(to_python(item.new_value))]
            else:
                entry['new_value'] = to_python(item.new_value)

            entry_group['entries'].append(entry)

        entries_group.append(entry_group)

    # Let's reverse the chronological order
    entries_group.reverse()

    # Remove first timeline item if it's solely a change to the target
    if (entries_group and len(entries_group[0]['entries']) == 1 and
        entries_group[0]['entries'][0]['field'] == SubmissionFields.TARGET):
        del entries_group[0]

    context['entries_group'] = entries_group

    if request.is_ajax():
        # The client will want to confirm that the response is relevant for
        # the unit on screen at the time of receiving this, so we add the uid.
        json = {'uid': unit.id}

        t = loader.get_template('unit/xhr-timeline.html')
        c = RequestContext(request, context)
        json['timeline'] = t.render(c).replace('\n', '')

        response = simplejson.dumps(json)
        return HttpResponse(response, mimetype="application/json")
    else:
        return render_to_response('unit/timeline.html', context,
                                  context_instance=RequestContext(request))
コード例 #20
0
ファイル: timeline.py プロジェクト: sshyran/zing
def _calculate_timeline(request, unit):
    submission_filter = Q(
        field__in=[
            SubmissionFields.TARGET,
            SubmissionFields.STATE,
            SubmissionFields.COMMENT,
            SubmissionFields.NONE,
        ]
    ) | Q(type__in=SubmissionTypes.SUGGESTION_TYPES)
    timeline = (
        Submission.objects.filter(unit=unit)
        .filter(submission_filter)
        .exclude(field=SubmissionFields.COMMENT, creation_time=unit.commented_on)
        .order_by("id")
    )
    User = get_user_model()
    entries_group = []
    context = {}
    timeline_fields = [
        "type",
        "old_value",
        "new_value",
        "submitter_id",
        "creation_time",
        "translation_project__language__code",
        "field",
        "suggestion_id",
        "suggestion__target_f",
        "quality_check__name",
        "submitter__username",
        "submitter__full_name",
        "suggestion__user__full_name",
        "submitter__email",
        "suggestion__user__username",
    ]

    grouped_timeline = groupby(
        timeline.values(*timeline_fields),
        key=lambda item: "\001".join(
            [
                str(x)
                for x in [
                    item["submitter_id"],
                    item["creation_time"],
                    item["suggestion_id"],
                ]
            ]
        ),
    )

    # Group by submitter id and creation_time because
    # different submissions can have same creation time
    for key_, values in grouped_timeline:
        entry_group = {
            "entries": [],
        }

        for item in values:
            # Only add creation_time information for the whole entry group once
            entry_group["datetime"] = item["creation_time"]

            # Only add submitter information for the whole entry group once
            entry_group.setdefault("submitter", ProxyTimelineUser(item))

            context.setdefault(
                "language",
                ProxyTimelineLanguage(item["translation_project__language__code"]),
            )

            entry = {
                "field": item["field"],
                "field_name": SubmissionFields.NAMES_MAP.get(item["field"], None),
                "type": item["type"],
            }
            if item["field"] == SubmissionFields.STATE:
                entry["old_value"] = STATES_MAP[int(to_python(item["old_value"]))]
                entry["new_value"] = STATES_MAP[int(to_python(item["new_value"]))]
            elif item["suggestion_id"]:
                entry.update(
                    {
                        "suggestion_text": item["suggestion__target_f"],
                        "suggestion_description": mark_safe(
                            _get_suggestion_description(item)
                        ),
                    }
                )
            elif item["quality_check__name"]:
                check_name = item["quality_check__name"]
                check_url = u"".join(
                    [reverse("pootle-checks-descriptions"), "#", check_name]
                )
                entry.update(
                    {
                        "check_name": check_name,
                        "check_display_name": check_names[check_name],
                        "checks_url": check_url,
                    }
                )
            else:
                entry["new_value"] = to_python(item["new_value"])

            entry_group["entries"].append(entry)

        entries_group.append(entry_group)

    has_creation_entry = (
        len(entries_group) > 0 and entries_group[0]["datetime"] == unit.creation_time
    )
    if has_creation_entry:
        entries_group[0]["created"] = True
    else:
        created = {"created": True, "submitter": User.objects.get_system_user()}

        if unit.creation_time:
            created["datetime"] = unit.creation_time
        entries_group[:0] = [created]

    # Let's reverse the chronological order
    entries_group.reverse()
    context["entries_group"] = entries_group
    t = loader.get_template("editor/units/xhr_timeline.html")
    return t.render(context=context, request=request)
コード例 #21
0
    def get_submission_info(self):
        """Returns a dictionary describing the submission.

        The dict includes the user (with link to profile and gravatar),
        a type and translation_action_type describing the action performed,
        and when it was performed.
        """
        result = {}

        if self.unit is not None:
            result.update({
                'source': truncatechars(self.unit, 50),
                'uid': self.unit.id,
            })

            if self.quality_check is not None:
                check_name = self.quality_check.name
                result.update({
                    'check':
                    check_name,
                    'check_displayname':
                    check_names.get(check_name, check_name),
                })

        if (self.suggestion and self.type
                in (SubmissionTypes.SUGG_ACCEPT, SubmissionTypes.SUGG_REJECT)):
            displayuser = self.suggestion.reviewer
        else:
            # Sadly we may not have submitter information in all the
            # situations yet
            # TODO check if it is true
            if self.submitter:
                displayuser = self.submitter
            else:
                User = get_user_model()
                displayuser = User.objects.get_nobody_user()

        result.update({
            "email": displayuser.email_hash,
            "displayname": displayuser.display_name,
            "username": displayuser.username,
            "type": self.type,
            "mtime": int(dateformat.format(self.creation_time, 'U')),
        })

        # TODO Fix bug 3011 and remove the following code related to
        # TranslationActionTypes.

        if self.type in SubmissionTypes.EDIT_TYPES:
            translation_action_type = None
            try:
                if self.field == SubmissionFields.TARGET:
                    if self.new_value != '':
                        # Note that we analyze current unit state:
                        # if this submission is not last unit state
                        # can be changed
                        if self.unit.state == TRANSLATED:

                            if self.old_value == '':
                                translation_action_type = \
                                    TranslationActionTypes.TRANSLATED
                            else:
                                translation_action_type = \
                                    TranslationActionTypes.EDITED
                        elif self.unit.state == FUZZY:
                            if self.old_value == '':
                                translation_action_type = \
                                    TranslationActionTypes.PRE_TRANSLATED
                            else:
                                translation_action_type = \
                                    TranslationActionTypes.EDITED
                    else:
                        translation_action_type = \
                            TranslationActionTypes.REMOVED
                elif self.field == SubmissionFields.STATE:
                    # Note that a submission where field is STATE
                    # should be created before a submission where
                    # field is TARGET

                    translation_action_type = {
                        TRANSLATED: TranslationActionTypes.REVIEWED,
                        FUZZY: TranslationActionTypes.NEEDS_WORK
                    }.get(int(to_python(self.new_value)), None)

            except AttributeError:
                return result

            result['translation_action_type'] = translation_action_type

        return result
コード例 #22
0
ファイル: timeline.py プロジェクト: ii0/pootle
 def context(self):
     return dict(value=format_html(
         u"{} <span class='timeline-arrow'></span> {}",
         STATES_MAP[int(to_python(self.submission.old_value))],
         STATES_MAP[int(to_python(self.submission.new_value))]),
                 state=True)