Example #1
0
 def test_delete_tasks(self):
     # Add a review task for the last SubtitleVersion
     Task(team=self.team,
          team_video=self.team_video,
          assignee=None,
          language=self.language.language_code,
          type=Task.TYPE_IDS['Review'],
          new_subtitle_version=self.versions[-1]).save()
     # add a completed review task for the one before that
     Task(team=self.team,
          team_video=self.team_video,
          assignee=None,
          language=self.language.language_code,
          type=Task.TYPE_IDS['Review'],
          approved=Task.APPROVED_IDS['Approved'],
          new_subtitle_version=self.versions[-1]).save()
     # add a task for another video, but with the same language
     other_team_video = TeamVideoFactory(team=self.team, added_by=self.user)
     Task(team=self.team,
          team_video=other_team_video,
          assignee=None,
          language=self.language.language_code,
          type=Task.TYPE_IDS['Translate']).save()
     self.check_task_count(3)
     # deleting the language should delete both tasks for this video, but
     # not the task for the other video.
     self.language.nuke_language()
     self.check_task_count(1)
Example #2
0
def dashboard(request):
    user = request.user

    tasks = user.open_tasks()

    widget_settings = {}
    from apps.widget.rpc import add_general_settings
    add_general_settings(request, widget_settings)

    # For perform links on tasks
    video_pks = [t.team_video.video_id for t in tasks]
    video_urls = dict([
        (vu.video_id, vu.effective_url)
        for vu in VideoUrl.objects.filter(video__in=video_pks, primary=True)
    ])

    Task.add_cached_video_urls(tasks)

    context = {
        'user_info': user,
        'team_activity': Action.objects.for_user_team_activity(user)[:8],
        'video_activity': Action.objects.for_user_video_activity(user)[:8],
        'tasks': tasks,
        'widget_settings': widget_settings,
    }

    return direct_to_template(request, 'profiles/dashboard.html', context)
Example #3
0
 def test_sent_back(self):
     self.setup_team()
     # go through the subtitle task phase
     task = Task(team=self.team,
                 team_video=self.team_video,
                 language='en',
                 type=Task.TYPE_IDS['Subtitle'],
                 assignee=self.user)
     lang = self.add_completed_subtitles('en', [
         (0, 1000, "Hello, ", {
             'new_paragraph': True
         }),
         (1500, 2500, "World"),
     ],
                                         visibility='private')
     task.new_subtitle_version = lang.get_tip(public=False)
     review_task = task.complete()
     # have the video get sent back in the review phase
     self.assertEquals(review_task.type, Task.TYPE_IDS['Review'])
     review_task.assignee = self.user
     review_task.approved = Task.APPROVED_IDS['Rejected']
     new_subtitle_task = review_task.complete()
     # now in the approval phase
     self.assertEquals(new_subtitle_task.type, Task.TYPE_IDS['Subtitle'])
     self.assertEquals(
         views.LanguageList(self.video).items, [
             ('English', 'needs-review', ['original', 'needs editing'
                                          ], lang.get_absolute_url()),
         ])
Example #4
0
 def test_add_task_invalidates_video_cache(self):
     team_video = TeamVideoFactory()
     with assert_invalidates_model_cache(team_video.video):
         task = Task(team=team_video.team,
                     team_video=team_video,
                     language='en',
                     type=Task.TYPE_IDS['Translate'])
         task.save(update_team_video_index=False)
Example #5
0
    def test_delete_translation_tasks(self):
        # We should delete translation tasks if there are no more languages
        # with public versions available.  However, we should not delete
        # in-progress translation tasks, or review/approve tasks.  Those can
        # continue alright with the forked language.

        # make a translation task
        Task(team=self.team,
             team_video=self.team_video,
             assignee=None,
             language='de',
             type=Task.TYPE_IDS['Translate']).save()
        # make an in-progress translation task
        Task(team=self.team,
             team_video=self.team_video,
             language='ja',
             type=Task.TYPE_IDS['Translate'],
             assignee=self.user).save()
        v = pipeline.add_subtitles(self.video, 'ja', None, action='save-draft')
        # make review/approve tasks
        TaskFactory.create_review(self.team_video, 'es', self.user)
        TaskFactory.create_approve(self.team_video, 'sv', self.user)
        # check initial task counts
        translate_qs = Task.objects.incomplete_translate().filter(
            language='de')
        in_progress_qs = Task.objects.incomplete_translate().filter(
            language='ja')
        review_qs = Task.objects.incomplete_review().filter(language='es')
        approve_qs = Task.objects.incomplete_approve().filter(language='sv')

        self.assertEquals(translate_qs.count(), 1)
        self.assertEquals(in_progress_qs.count(), 1)
        self.assertEquals(review_qs.count(), 1)
        self.assertEquals(approve_qs.count(), 1)
        # make a second language.  If we delete that language, we should still
        # keep translation tasks.
        other_lang_version = pipeline.add_subtitles(self.video, 'fr', None)
        other_lang_version.subtitle_language.nuke_language()
        self.assertEquals(translate_qs.count(), 1)
        self.assertEquals(in_progress_qs.count(), 1)
        self.assertEquals(review_qs.count(), 1)
        self.assertEquals(approve_qs.count(), 1)
        # but when we delete our original language, then there's no source
        # languages, so we should delete the translation task, but keep
        # in-progress translation tasks, as well as review tasks
        self.language.nuke_language()
        self.assertEquals(translate_qs.count(), 0)
        self.assertEquals(in_progress_qs.count(), 1)
        self.assertEquals(review_qs.count(), 1)
        self.assertEquals(approve_qs.count(), 1)
Example #6
0
def _create_necessary_tasks(version, team_video, workflow, committer,
                            complete):
    """Create any necessary tasks for the newly added version.

    By the time we call this function we know that:

    * There are no existing open tasks for this version/language.
    * The committer cannot bypass moderation.

    So we may (or may not) need to create a task for this version/language.

    """
    from teams.models import Task

    if complete:
        # If the subtitles are complete, then the new task will be either
        # a review or approve, depending on the team.
        if workflow.review_allowed:
            task_type = Task.TYPE_IDS['Review']
        elif workflow.approve_allowed:
            task_type = Task.TYPE_IDS['Approve']
        else:
            # Note that we may not have selected either of these, if the team
            # does not require review or approval.  That's okay, we're done in
            # that case.
            return
    else:
        # Otherwise the new task will be a subtitle or translate, depending
        # on the type of subs.
        # TODO: More advanced logic here?
        if version.subtitle_language.is_primary_audio_language():
            task_type = Task.TYPE_IDS['Subtitle']
        else:
            task_type = Task.TYPE_IDS['Translate']

    # We now know the type of task we need to create, so go ahead and make it.
    task = Task(team=team_video.team,
                team_video=team_video,
                language=version.language_code,
                type=task_type,
                new_subtitle_version=version)

    # Assign it to the correct user.
    if task.get_type_display() in ('Subtitle', 'Translate'):
        # If it's a subtitle/translate task, then someone just added
        # some incomplete subtitles.  We'll assign it to them by
        # default.
        task.assignee = committer
    else:
        # Otherwise it's a review/approve task, so we'll see if anyone
        # has reviewed or approved this before.  If so, assign it back
        # to them.  Otherwise just leave it unassigned.
        task.assignee = task._find_previous_assignee(task.get_type_display())

    task.save()
Example #7
0
    def _moderate_incomplete_version(self, subtitle_version, user):
        """ Verifies if it's possible to create a transcribe/translate task (if there's
        no other transcribe/translate task) and tries to assign to user. 
        Also, if the video belongs to a team, change its status.
        """

        team_video = subtitle_version.video.get_team_video()

        if not team_video:
            return

        language = subtitle_version.language.language

        # if there's any incomplete task, we can't create yet another.
        transcribe_task = team_video.task_set.incomplete().filter(
            language=language)

        if transcribe_task.exists():
            return

        subtitle_version.moderation_status = WAITING_MODERATION
        subtitle_version.save()

        if subtitle_version.is_dependent():
            task_type = Task.TYPE_IDS['Translate']
            can_do = can_create_and_edit_translations
        else:
            task_type = Task.TYPE_IDS['Subtitle']
            can_do = can_create_and_edit_subtitles

        task = Task(team=team_video.team,
                    team_video=team_video,
                    language=language,
                    type=task_type)

        if can_do(user, team_video):
            task.assignee = user

        task.save()
Example #8
0
    def _create_review_or_approve_task(self, subtitle_version):
        team_video = subtitle_version.video.get_team_video()
        lang = subtitle_version.subtitle_language.language_code
        workflow = Workflow.get_for_team_video(team_video)

        if workflow.review_allowed:
            type = Task.TYPE_IDS['Review']
            can_do = partial(can_review, allow_own=True)
        elif workflow.approve_allowed:
            type = Task.TYPE_IDS['Approve']
            can_do = can_approve
        else:
            return None

        # TODO: Dedupe this and Task._find_previous_assignee

        # Find the assignee.
        #
        # For now, we'll assign the review/approval task to whomever did
        # it last time (if it was indeed done), but only if they're
        # still eligible to perform it now.
        last_task = team_video.task_set.complete().filter(
            language=lang, type=type).order_by('-completed')[:1]

        assignee = None
        if last_task:
            candidate = last_task[0].assignee
            if candidate and can_do(team_video, candidate, lang):
                assignee = candidate

        task = Task(team=team_video.team,
                    team_video=team_video,
                    assignee=assignee,
                    language=lang,
                    type=type)

        task.set_expiration()
        task.new_subtitle_version = subtitle_version

        if task.get_type_display() in ['Review', 'Approve']:
            task.new_review_base_version = subtitle_version

        task.save()
Example #9
0
    def test_translation_tasks_not_blocked(self):
        # test that translation tasks are not blocked if the admin unpublishes
        # the version

        # make a translation task
        task = Task(team=self.team,
                    team_video=self.team_video,
                    assignee=self.user,
                    type=Task.TYPE_IDS['Translate'],
                    language='ru')
        task.save()
        # complete the translation task to create an approval task
        lang = self.make_dependent_language('ru', self.versions[-1])
        task.new_subtitle_version = lang.get_tip()
        approve_task = task.complete()
        # complete the parent subtitles language, so that that's not an issue
        # for is_blocked().
        self.language.subtitles_complete = True
        self.language.save()
        # unpublish the last version and check that that doesn't block the
        # approval task
        self.versions[-1].visibility_override = 'private'
        self.versions[-1].save()
        self.assertEquals(approve_task.is_blocked(), False)
Example #10
0
    def test_can_create_task_subtitle(self):
        team, user, outsider = self.team, self.user, self.outsider

        # When no subtitles exist yet, it depends on the team's task creation
        # policy.
        self.assertTrue(can_create_task_subtitle(self.nonproject_video))

        # Any team member.
        team.task_assign_policy = Team.TASK_ASSIGN_IDS['Any team member']
        team.save()

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertTrue(
                    can_create_task_subtitle(self.nonproject_video, user))

        self.assertFalse(
            can_create_task_subtitle(self.nonproject_video, outsider))

        # Manager+
        team.task_assign_policy = Team.TASK_ASSIGN_IDS['Managers and admins']
        team.save()

        for r in [ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertTrue(
                    can_create_task_subtitle(self.nonproject_video, user))

        for r in [ROLE_CONTRIBUTOR]:
            with self.role(r):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        for r in [ROLE_MANAGER, ROLE_ADMIN]:
            with self.role(r, self.test_project):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        self.assertFalse(
            can_create_task_subtitle(self.nonproject_video, outsider))

        # Admin+
        team.task_assign_policy = Team.TASK_ASSIGN_IDS['Admins only']
        team.save()

        for r in [ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertTrue(
                    can_create_task_subtitle(self.nonproject_video, user))

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER]:
            with self.role(r):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        for r in [ROLE_ADMIN]:
            with self.role(r, self.test_project):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        self.assertFalse(
            can_create_task_subtitle(self.nonproject_video, outsider))

        # Once a subtitle task exists, no one can create another.
        team.task_assign_policy = Team.TASK_ASSIGN_IDS['Any team member']
        team.save()

        t = Task(type=Task.TYPE_IDS['Subtitle'],
                 team=team,
                 team_video=self.nonproject_video)
        t.save()

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        # Even if it's completed.
        t.completed = datetime.datetime.now()
        t.save()

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        # Unless it's deleted, of course.
        t.deleted = True
        t.save()

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertTrue(
                    can_create_task_subtitle(self.nonproject_video, user))

        # Once subtitles exist, no one can create a new task.
        helpers._add_language_via_pipeline(self.nonproject_video.video, 'en')

        self.assertFalse(can_create_task_subtitle(self.nonproject_video))

        for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]:
            with self.role(r):
                self.assertFalse(
                    can_create_task_subtitle(self.nonproject_video, user))

        self.assertFalse(
            can_create_task_subtitle(self.nonproject_video, outsider))
Example #11
0
    def test_moderated_notifies_only_when_published(self):
        """
        Set up a public team, add new video and new version.
        Notification should be sent.
        Setup  a team with moderated videos
        """
        from teams.moderation_const import WAITING_MODERATION, APPROVED

        def video_with_two_followers():
            v, c = Video.get_or_create_for_url(
                "http://blip.tv/file/get/Miropcf-AboutUniversalSubtitles847.ogv"
            )
            f1 = User.objects.all()[0]
            f2 = User.objects.all()[1]
            f1.notify_by_email = f2.notify_by_email = True
            f1.save()
            f2.save()
            v.followers.add(f1, f2)
            return v

        def new_version(v):

            language, created = SubtitleLanguage.objects.get_or_create(
                video=v, language='en', is_original=True)
            prev = language.version(public_only=False)
            version_no = 0
            if prev:
                version_no = prev.version_no + 1
            sv = SubtitleVersion(language=language,
                                 user=User.objects.all()[2],
                                 version_no=version_no,
                                 datetime_started=datetime.now())
            sv.save()
            s = Subtitle(version=sv,
                         subtitle_text=str(version_no + random.random()),
                         subtitle_order=1,
                         subtitle_id=str(version_no),
                         start_time=random.random())
            s.save()
            return sv

        v = video_with_two_followers()
        mail.outbox = []
        from videos.tasks import video_changed_tasks
        v = video_with_two_followers()
        sv = new_version(v)
        video_changed_tasks(v.pk, sv.pk)
        # notifications are only sent on the second version of a video
        # as optimization
        sv = new_version(v)
        video_changed_tasks(v.pk, sv.pk)
        # video is public , followers should be notified
        self.assertEquals(len(mail.outbox), 2)
        mail.outbox = []
        # add to a moderated video
        team = Team.objects.create(slug='my-team',
                                   name='myteam',
                                   workflow_enabled=True)
        workflow = Workflow(team=team, review_allowed=20, approve_allowed=20)
        workflow.save()

        tv = TeamVideo(team=team, video=v, added_by=User.objects.all()[2])
        tv.save()
        sv = new_version(v)
        # with the widget, this would set up correctly
        sv.moderation_status = WAITING_MODERATION
        sv.save()

        video_changed_tasks(v.pk, sv.pk)
        sv = SubtitleVersion.objects.get(pk=sv.pk)
        self.assertFalse(sv.is_public)
        # approve video
        t = Task(type=40,
                 approved=20,
                 team_video=tv,
                 team=team,
                 language='en',
                 subtitle_version=sv)
        t.save()
        t.complete()
        video_changed_tasks(v.pk, sv.pk)

        self.assertEqual(len(mail.outbox), 2)
Example #12
0
    def save_subtitles(self,
                       parser,
                       video=None,
                       language=None,
                       update_video=True,
                       is_complete=True):
        video = video or self.cleaned_data['video']

        if not video.has_original_language():
            self._save_original_language(video,
                                         self.cleaned_data['video_language'])

        if language:
            self._sl_created = False
            language = language
        else:
            language, self._sl_created = self._find_appropriate_language(
                video, self.cleaned_data['language'])

        language = save_subtitle(video, language, parser, self.user,
                                 update_video)

        # If there are any outstanding tasks for this language, associate the
        # new version with them.
        team_video = video.get_team_video()
        if team_video:
            new_version = language.latest_version(public_only=False)

            # TODO: Refactor all of this out into some kind of generic "add subtitles" pipeline.

            # Determine if we need to moderate these subtitles and create a
            # review/approve task for them.
            workflow = team_video.get_workflow()
            # user can bypass moderation if:
            # 1) he is a moderator and
            # 2) it's a post-publish edit
            # 3) subtitle is complete
            can_bypass_moderation = (is_complete and not self._sl_created
                                     and can_publish_edits_immediately(
                                         team_video, self.user,
                                         language.language))

            if can_bypass_moderation:
                new_version.moderate = APPROVED
            elif workflow.review_allowed or workflow.approve_allowed:
                new_version.moderation_status = WAITING_MODERATION
            else:
                new_version.moderation_status = UNMODERATED

            new_version.save()

            outstanding_tasks = team_video.task_set.incomplete().filter(
                language__in=[language.language, ''])

            if outstanding_tasks.exists():
                if new_version.moderation_status != WAITING_MODERATION:
                    outstanding_tasks.update(subtitle_version=new_version,
                                             language=language.language)
            elif not can_bypass_moderation:
                # we just need to create review/approve/subtitle if the language
                # is a new one or, if it's a post-publish edit, if the user can't
                # approve subtitles by himself.
                task_type = None

                if new_version.is_synced() and is_complete:
                    if workflow.review_allowed:
                        task_type = Task.TYPE_IDS['Review']
                    elif workflow.approve_allowed:
                        task_type = Task.TYPE_IDS['Approve']
                else:
                    task_type = Task.TYPE_IDS['Subtitle']

                if task_type:
                    task = Task(team=team_video.team,
                                team_video=team_video,
                                language=language.language,
                                type=task_type,
                                subtitle_version=new_version)

                    if not self._sl_created:
                        task.assignee = task._find_previous_assignee(
                            Task.TYPE_NAMES[task_type])
                    else:
                        if task_type == Task.TYPE_IDS['Subtitle']:
                            task.assignee = self.user

                    task.save()

        return language