コード例 #1
0
class ArgumentCell(LayoutCell):
    model_properties = [
        'id', 'title', 'abstract', 'details', 'created_at', 'author'
    ]

    footer = Cell.fragment('argument_footer')

    def details_link(self):
        if 'details_link' in self.options:
            return self.options['details_link']

        return self.self_link
コード例 #2
0
class ArgumentRelationCell(LayoutCell):
    model_properties = ['id', 'proposition', 'argument', 'score']

    voting = Cell.fragment('argument_relation_voting')

    def show_voting(self):
        return self._request.permitted_for_current_user(
            self._model, VotePermission)

    def show_ca_button(self):
        return  # self.current_user is not None

    def vote(self):
        return self._model.user_vote(self.current_user)

    def proposition_url(self):
        return self.link(self._model.proposition)

    def argument_url(self):
        return self.link(self._model.argument)

    def proposition_title(self):
        proposition = self._model.proposition
        if proposition.voting_identifier:
            return proposition.voting_identifier + ': ' + proposition.title
        else:
            return proposition.title

    def argument_title(self):
        return self.argument.title

    def upvote_button_disabled_class(self):
        return 'disabled' if self.vote is not None and self.vote.weight == 1 else ''

    def downvote_button_disabled_class(self):
        return 'disabled' if self.vote is not None and self.vote.weight == -1 else ''

    def revoke_vote_button_disabled_class(self):
        return 'disabled' if self.vote is None or self.vote.weight == 0 else ''

    def vote_action_url(self):
        return self.link(self._model, 'vote')
コード例 #3
0
    class TestCell(Cell):
        model_properties = ['id', 'title']
        markup_class = DummyMarkup

        def _get_cell_class(self, model, view):
            return self.__class__

        def test_url(self):
            return "https://example.com/test"

        @Cell.fragment
        def alternate_fragment(self, **k):
            return self.render_template('alternate_template', **k)

        @Cell.fragment
        def fragment_without_params(self):
            pass

        cannot_call_this = None

        fragment_from_name = Cell.fragment('name')
コード例 #4
0
class PropositionCell(LayoutCell):

    model_properties = [
        'abstract',
        'ballot',
        'content',
        'created_at',
        'derivations',
        'external_discussion_url',
        'id',
        'modifies',
        'motivation',
        'replacements',
        'replaces',
        'tags',
        'title'
    ]

    actions = Cell.fragment('proposition_actions')
    tabs = Cell.fragment('proposition_tabs')
    small = Cell.fragment('proposition_small')
    card = Cell.fragment('proposition_card')

    @Cell.fragment
    def status(self):
        status_to_variant = {
            PropositionStatus.DRAFT: 'submitted',
            PropositionStatus.CHANGING: 'submitted',
            PropositionStatus.SUBMITTED: 'submitted',
            PropositionStatus.ABANDONED: 'submitted',
            PropositionStatus.QUALIFIED: 'submitted',
            PropositionStatus.SCHEDULED: 'scheduled',
            PropositionStatus.VOTING: 'scheduled',
            PropositionStatus.FINISHED: 'finished',
        }
        variant = status_to_variant[self._model.status]
        template = f"proposition/proposition_status_{variant}.j2.jade"
        return self.render_template(template)

    @Cell.fragment
    def history(self):
        status_to_variant = {
            PropositionStatus.DRAFT: 'submitted',
            PropositionStatus.CHANGING: 'submitted',
            PropositionStatus.SUBMITTED: 'submitted',
            PropositionStatus.ABANDONED: 'submitted',
            PropositionStatus.QUALIFIED: 'submitted',
            PropositionStatus.SCHEDULED: 'scheduled',
            PropositionStatus.VOTING: 'scheduled',
            PropositionStatus.FINISHED: 'finished',
        }
        variant = status_to_variant[self._model.status]
        template = f"proposition/proposition_history_{variant}.j2.jade"
        return self.render_template(template)

    def associated_url(self):
        return self.link(self._model, 'associated')

    def report_url(self):
        return self._s.app.report_url

    def share_url(self):
        if self._app.settings.share.use_url_shortener:
            from ekklesia_portal.helper.url_shortener import make_tiny
            return make_tiny(self.self_link)
        else:
            return self.self_link[:69]

    @log_call
    def share_email_url(self):
        share_email_topic = (self._s.share.email_topic[self.language]
                             .format(
                                 voting_identifier=self._model.voting_identifier,
                                 title=self._model.title[:140]))

        share_email_body = self._s.share.email_body[self.language] + self.share_url
        email_url = urllib.parse.urlencode({'subject': share_email_topic,
                                            'body': share_email_body},
                                           quote_via=urllib.parse.quote)
        email_url = 'mailto:?' + email_url
        return email_url

    @log_call
    def share_twitter_url(self):
        share_tweet_msg = (self._s.share.tweet_msg[self.language]
                           .format(
                               voting_identifier=self._model.voting_identifier,
                               title=self._model.title[:70]))

        twitter_url = urllib.parse.urlencode({'hashtags': self._app.settings.share.hashtag,
                                              'related': self._app.settings.share.promote_account,
                                              'text': share_tweet_msg,
                                              'tw_p': 'tweetbutton',
                                              'url': self.share_url})
        twitter_url = 'https://twitter.com/intent/tweet?' + twitter_url
        return twitter_url

    def ballot_url(self):
        return self.link(self._model.ballot)

    def ballot_title(self):
        ballot = self._model.ballot
        if ballot.name:
            return ballot.name

        return f'# {ballot.id}'

    def discussion_url(self):
        return self.link(self._model)

    def propositions_tag_url(self, tag):
        return self.class_link(Propositions, dict(tag=tag.name))

    def is_supported_by_current_user(self):
        return self._model.support_by_user(self.current_user) is not None

    def discussion_link_class(self):
        return 'active' if self.options.get('active_tab') == 'discussion' else ''

    def associated_link_class(self):
        return 'active' if self.options.get('active_tab') == 'associated' else ''

    def new_associated_proposition_url(self, association_type):
        return self.class_link(Propositions, dict(association_type=association_type), '+new')

    def new_pro_argument_url(self):
        return self.class_link(
            ArgumentRelations,
            dict(proposition_id=self._model.id, relation_type=ArgumentType.PRO.name),
            '+new')

    def new_con_argument_url(self):
        return self.class_link(
            ArgumentRelations,
            dict(proposition_id=self._model.id, relation_type=ArgumentType.CONTRA.name),
            '+new')

    def supporter_count(self):
        return self._model.active_supporter_count

    def support_action(self):
        return self.link(self._model, 'support')

    def pro_argument_relations(self):
        relations = [p for p in self._model.proposition_arguments if p.argument_type == ArgumentType.PRO]
        return sorted(relations, key=attrgetter('score'), reverse=True)

    def contra_argument_relations(self):
        relations = [p for p in self._model.proposition_arguments if p.argument_type == ArgumentType.CONTRA]
        return sorted(relations, key=attrgetter('score'), reverse=True)

    def argument_count(self):
        return len(self._model.proposition_arguments)

    def full_title(self):
        if self._model.voting_identifier:
            return self._model.voting_identifier + ': ' + self._model.title
        else:
            return self._model.title

    def show_support_actions(self):
        return self._request.permitted_for_current_user(self._model, SupportPermission)

    def show_create_argument(self):
        return self._request.permitted_for_current_user(ArgumentRelations(), CreatePermission)

    def show_create_associated_proposition(self):
        return self._request.permitted_for_current_user(self._model, CreatePermission)

    def voting_phase(self):
        return self._model.ballot.voting

    def voting_result_state(self):
        result = self._model.ballot.result
        if result:
            try:
                return OpenSlidesVotingResult(result.get(self._model.voting_identifier, {}).get("state"))
            except ValueError:
                return

    def voting_result_symbol(self):
        symbols = {
            OpenSlidesVotingResult.ACCEPTED: "fas fa-check",
            OpenSlidesVotingResult.REJECTED: "fas fa-ban",
            OpenSlidesVotingResult.NOT_DECIDED: "fas fa-spinner"
        }
        return symbols.get(self.voting_result_state)

    def show_edit_button(self):
        return self.options.get('show_edit_button') and self._request.permitted_for_current_user(self._model, EditPermission)

    def edit_url(self):
        return self.link(self._model, 'edit')

    def note_url(self):
        tmp = self.class_link(PropositionNote, variables={'proposition_id': self._model.id, 'user_id': self._request.current_user.id}, name='edit')
        return tmp
コード例 #5
0
class PropositionsCell(LayoutCell):

    model_properties = [
        'department',
        'phase',
        'search',
        'section',
        'sort',
        'status_values',
        'subject_area',
        'tag_values',
        'type',
        'without_tag_values',
    ]

    pager = Cell.fragment("propositions_pager")

    def propositions(self):
        is_admin = self.current_user and self._request.identity.has_global_admin_permissions
        return list(self._model.propositions(self._request.q, is_admin))

    def prop_count(self):
        is_admin = self.current_user and self._request.identity.has_global_admin_permissions
        return self._model.propositions(self._request.q, is_admin, count=True)

    def page_count(self):
        per_page = self.prop_per_page
        if per_page <= 0:
            return -1
        else:
            return int(math.ceil(self.prop_count / per_page))

    def prop_per_page(self):
        return self._model.propositions_per_page()

    def page(self):
        return self._model.page or 1

    # Overrides the base method in LayoutCell
    def search_query(self):
        return self._model.build_search_query()

    def change_self_link(self, **kwargs):
        propositions = self._model.replace(**kwargs)
        return self.link(propositions)

    def voting_phase_title(self, phase):
        voting_phase = self._request.q(VotingPhase).filter(
            func.lower(VotingPhase.name) == func.lower(phase)).scalar()
        if voting_phase is None:
            return phase

        return voting_phase.title

    def proposition_type_name(self, proposition_type):
        proposition_type = self._request.q(PropositionType).filter(
            func.lower(PropositionType.abbreviation) == func.lower(
                proposition_type)).scalar()
        if proposition_type is None:
            return proposition_type

        return proposition_type.name

    def visibility_values(self):
        if self.current_user and self._request.identity.has_global_admin_permissions:
            return self._model.visibility_values
        else:
            return None

    def export_csv_url(self):
        return (url_change_query(self.self_link, media_type="text/csv"))
コード例 #6
0
class PropositionCell(LayoutCell):

    _model: Proposition

    model_properties = [
        'abstract',
        'author',
        'ballot',
        'content',
        'created_at',
        'submitted_at',
        'qualified_at',
        'derivations',
        'external_discussion_url',
        'id',
        'modifies',
        'motivation',
        'replacements',
        'replaces',
        'submitter_invitation_key',
        'tags',
        'title',
        'secret_voters_count',
        'secret_voters_user_count',
        'secret_voting_quorum',
    ]

    actions = Cell.fragment('proposition_actions')
    tabs = Cell.fragment('proposition_tabs')
    small = Cell.fragment('proposition_small')
    card = Cell.fragment('proposition_card')

    @Cell.fragment
    def status(self):
        status_to_variant = {
            PropositionStatus.DRAFT: 'draft',
            PropositionStatus.CHANGING: 'submitted',
            PropositionStatus.SUBMITTED: 'submitted',
            PropositionStatus.ABANDONED: 'submitted',
            PropositionStatus.QUALIFIED: 'submitted',
            PropositionStatus.SCHEDULED: 'scheduled',
            PropositionStatus.VOTING: 'scheduled',
            PropositionStatus.FINISHED: 'finished',
        }
        variant = status_to_variant[self._model.status]
        template = f"proposition/status/proposition_status_{variant}.j2.jade"
        return self.render_template(template)

    @Cell.fragment
    def history(self):
        status_to_variant = {
            PropositionStatus.DRAFT: 'draft',
            PropositionStatus.CHANGING: 'submitted',
            PropositionStatus.SUBMITTED: 'submitted',
            PropositionStatus.ABANDONED: 'submitted',
            PropositionStatus.QUALIFIED: 'submitted',
            PropositionStatus.SCHEDULED: 'scheduled',
            PropositionStatus.VOTING: 'scheduled',
            PropositionStatus.FINISHED: 'finished',
        }
        variant = status_to_variant[self._model.status]
        template = f"proposition/history/proposition_history_{variant}.j2.jade"
        return self.render_template(template)

    @Cell.fragment
    def detail_top(self):
        variant = self._model.status
        if variant not in (PropositionStatus.DRAFT,
                           PropositionStatus.SUBMITTED,
                           PropositionStatus.QUALIFIED,
                           PropositionStatus.SCHEDULED):
            return ""
        template = f"proposition/detail_top/proposition_detail_top_{variant}.j2.jade"
        return self.render_template(template)

    def associated_url(self):
        return self.link(self._model, 'associated')

    def report_url(self):
        return self._s.app.report_url

    def share_url(self):
        if self._app.settings.share.use_url_shortener:
            return make_tiny(self.self_link)

        return self.self_link[:69]

    @log_call
    def share_email_url(self):
        share_email_topic = (self._s.share.email_topic[self.language].format(
            voting_identifier=self._model.voting_identifier,
            title=self._model.title[:140]))

        share_email_body = self._s.share.email_body[
            self.language] + self.share_url
        email_url = urllib.parse.urlencode(
            {
                'subject': share_email_topic,
                'body': share_email_body
            },
            quote_via=urllib.parse.quote)
        email_url = 'mailto:?' + email_url
        return email_url

    @log_call
    def share_twitter_url(self):
        share_tweet_msg = (self._s.share.tweet_msg[self.language].format(
            voting_identifier=self._model.voting_identifier,
            title=self._model.title[:70]))

        twitter_url = urllib.parse.urlencode({
            'hashtags':
            self._app.settings.share.hashtag,
            'related':
            self._app.settings.share.promote_account,
            'text':
            share_tweet_msg,
            'tw_p':
            'tweetbutton',
            'url':
            self.share_url
        })
        twitter_url = 'https://twitter.com/intent/tweet?' + twitter_url
        return twitter_url

    def ballot_url(self):
        return self.link(self._model.ballot)

    def ballot_title(self):
        ballot = self._model.ballot
        if ballot.name:
            return ballot.name

        return f'# {ballot.id}'

    def discussion_url(self):
        return self.link(self._model)

    def propositions_tag_url(self, tag):
        return self.class_link(Propositions, dict(tags=tag.name))

    def current_user_is_supporter(self):
        if self.current_user is None:
            return False
        return self._model.support_by_user(self.current_user) is not None

    def current_user_is_submitter(self):
        if self.current_user is None:
            return False
        return self._model.user_is_submitter(self.current_user)

    def current_user_is_author(self):
        if self.current_user is None:
            return False
        return self._model.author == self.current_user

    def discussion_link_class(self):
        return 'active' if self.options.get(
            'active_tab') == 'discussion' else ''

    def associated_link_class(self):
        return 'active' if self.options.get(
            'active_tab') == 'associated' else ''

    def new_associated_proposition_url(self, association_type):
        return self.class_link(Propositions,
                               dict(association_type=association_type), '+new')

    def new_pro_argument_url(self):
        return self.class_link(
            ArgumentRelations,
            dict(proposition_id=self._model.id,
                 relation_type=ArgumentType.PRO.name), '+new')

    def new_con_argument_url(self):
        return self.class_link(
            ArgumentRelations,
            dict(proposition_id=self._model.id,
                 relation_type=ArgumentType.CONTRA.name), '+new')

    def missing_submitters_count(self):
        return self._model.ballot.proposition_type.policy.submitter_minimum - self._model.submitter_count

    def supporter_count(self):
        return self._model.active_supporter_count

    def become_submitter_action(self):
        return self.link(self._model, 'become_submitter')

    def secret_voting_action(self):
        return self.link(self._model, 'secret_voting')

    def support_action(self):
        return self.link(self._model, 'support')

    def pro_argument_relations(self):
        relations = [
            p for p in self._model.proposition_arguments
            if p.argument_type == ArgumentType.PRO
        ]
        return sorted(relations, key=attrgetter('score'), reverse=True)

    def contra_argument_relations(self):
        relations = [
            p for p in self._model.proposition_arguments
            if p.argument_type == ArgumentType.CONTRA
        ]
        return sorted(relations, key=attrgetter('score'), reverse=True)

    def argument_count(self):
        return len(self._model.proposition_arguments)

    def full_title(self):
        if self._model.voting_identifier:
            return self._model.voting_identifier + ': ' + self._model.title

        return self._model.title

    def ready_to_submit(self):
        return self._model.ready_to_submit

    def show_support_actions(self):
        return self._model.status in (
            PropositionStatus.SUBMITTED, PropositionStatus.QUALIFIED,
            PropositionStatus.SCHEDULED, PropositionStatus.VOTING
        ) and self._request.permitted_for_current_user(self._model,
                                                       SupportPermission)

    def show_submit_draft_action(self):
        return self._model.ready_to_submit and self._request.permitted_for_current_user(
            self._model, SubmitDraftPermission)

    def show_create_argument(self):
        return self._model.status in (
            PropositionStatus.SUBMITTED, PropositionStatus.QUALIFIED,
            PropositionStatus.SCHEDULED, PropositionStatus.VOTING,
            PropositionStatus.ABANDONED
        ) and self._request.permitted_for_current_user(ArgumentRelations(),
                                                       CreatePermission)

    def show_goto_arguments(self):
        return self._model.status in (PropositionStatus.SUBMITTED,
                                      PropositionStatus.QUALIFIED,
                                      PropositionStatus.SCHEDULED,
                                      PropositionStatus.VOTING,
                                      PropositionStatus.ABANDONED)

    def show_create_associated_proposition(self):
        return self._model.status in (
            PropositionStatus.DRAFT, PropositionStatus.SUBMITTED,
            PropositionStatus.QUALIFIED, PropositionStatus.SCHEDULED
        ) and self._request.permitted_for_current_user(self._model,
                                                       CreatePermission)

    def show_submitter_names(self):
        if self.current_user is None:
            return False

        if self._model.ballot.area.department in self.current_user.managed_departments:
            return True

        if self._request.identity.has_global_admin_permissions:
            return True

        if self._model.user_is_submitter(self.current_user):
            return True

        if self._model.author == self.current_user:
            return True

        return False

    def valid_submitter_invitation_key(self):
        key = self._request.GET.get("submitter_invitation_key")
        if key is None:
            return False
        return compare_digest(self._model.submitter_invitation_key, key)

    def voting_phase(self):
        return self._model.ballot.voting

    def voting_result_state(self):
        result = self._model.ballot.result
        if result:
            try:
                return OpenSlidesVotingResult(
                    result.get(self._model.voting_identifier, {}).get("state"))
            except ValueError:
                pass

        return None

    def voting_result_symbol(self):
        symbols = {
            OpenSlidesVotingResult.ACCEPTED: "fas fa-check",
            OpenSlidesVotingResult.REJECTED: "fas fa-ban",
            OpenSlidesVotingResult.NOT_DECIDED: "fas fa-spinner"
        }
        return symbols.get(self.voting_result_state)

    def show_edit_button(self):
        return self._request.permitted_for_current_user(
            self._model, EditPermission)

    def submit_draft_url(self):
        return self.link(self._model, 'submit_draft')

    def edit_url(self):
        return self.link(self._model, 'edit')

    def note_url(self):
        if self.current_user is None:
            return False
        return self.class_link(PropositionNote,
                               variables={
                                   'proposition_id': self._model.id,
                                   'user_id': self._request.current_user.id
                               },
                               name='edit')

    def become_submitter_url(self):
        return self.self_link + f"?submitter_invitation_key={self._model.submitter_invitation_key}"

    def submitter_names(self):
        return [
            pm.member.name for pm in self._model.propositions_member
            if pm.submitter
        ]

    def show_full_history(self):
        return self.options.get('show_details')

    def secret_voting(self):
        user_id = None
        if self.current_user is not None:
            user_id = self.current_user.id
        secret_record = self._request.db_session.query(SecretVoter).filter_by(
            member_id=user_id, ballot_id=self._model.ballot_id).scalar()
        stat = 'retracted'
        if secret_record is not None:
            stat = secret_record.status
        return stat == 'active'