Ejemplo n.º 1
0
class Report(VisualisableElement, Entity):
    """Report of ballot class"""
    name = renamer()
    electors = SharedMultipleProperty('electors')
    voters = SharedMultipleProperty('voters')
    subjects = SharedMultipleProperty('subjects')
    processes = SharedMultipleProperty('processes')
    ballot = SharedUniqueProperty('ballot', 'report')

    def __init__(self, ballottype, electors, subjects, **kwargs):
        kwargs['subjects'] = subjects
        kwargs['electors'] = electors
        super(Report, self).__init__(**kwargs)
        self.ballottype = BALLOT_TYPES[ballottype](self, **kwargs)
        if 'vote_process_id' in kwargs:
            self.ballottype.vote_process_id = kwargs['vote_process_id']

        self.result = None
        self.calculated = False

    def calculate_votes(self):
        """Return the result of ballot"""

        if not self.calculated:
            votes = self.ballot.ballot_box.votes
            self.result = self.ballottype.calculate_votes(votes)
            self.calculated = True
        else:
            return self.result

    def get_electeds(self):
        """Return the elected subject"""

        if not self.calculated:
            self.calculate_votes()

        return self.ballottype.get_electeds(self.result)

    def he_voted(self, user):
        mask = getattr(user, 'mask', None)
        return user in self.voters or (mask and mask in self.voters)

    def is_elector(self, user):
        mask = getattr(user, 'mask', None)
        return user in self.electors or (mask and mask in self.electors)

    def get_elector(self, user):
        if not self.is_elector(user):
            return None

        if user in self.electors:
            return user

        mask = getattr(user, 'mask', None)
        if mask and mask in self.electors:
            return mask

        return None
Ejemplo n.º 2
0
class CorrelableEntity(Entity):
    """
    A Correlable entity is an entity that can be correlated.
    A correlation is an abstract association between source entity
    and targets entities.
    """

    source_correlations = SharedMultipleProperty('source_correlations',
                                                 'source')
    target_correlations = SharedMultipleProperty('target_correlations',
                                                 'targets')

    @property
    def correlations(self):
        """Return all source correlations and target correlations"""
        result = [c.target for c in self.source_correlations]
        result.extend([c.source for c in self.target_correlations])
        return list(set(result))

    @property
    def all_source_related_contents(self):
        lists_targets = [(c.targets, c) for c in self.source_correlations]
        return [(target, c) for targets, c in lists_targets
                for target in targets]

    @property
    def all_target_related_contents(self):
        return [(c.source, c) for c in self.target_correlations]

    @property
    def all_related_contents(self):
        related_contents = self.all_source_related_contents
        related_contents.extend(self.all_target_related_contents)
        return related_contents

    @property
    def contextualized_contents(self):
        lists_contents = [(c.targets, c)
                          for c in self.contextualized_correlations]
        lists_contents = [(target, c) for targets, c in lists_contents
                          for target in targets]
        lists_contents.extend([(c.source, c)
                               for c in self.contextualized_correlations])
        return lists_contents

    def get_related_contents(self, type_=None, tags=[]):
        if type_ is None and not tags:
            return self.all_related_contents

        return [(content, c) for content, c in self.all_related_contents
                if (type_ is None or c.type == type_) and (not tags or any(
                    t in tags for t in c.tags))]
Ejemplo n.º 3
0
class FilmSynopses(SearchableEntity):
    """FilmSynopses class"""

    type_title = _('Film synopsis')
    icon = 'lac-icon icon-film-synopses'
    templates = {'default': 'lac:views/templates/film_synopses_result.pt',
                 'bloc': 'lac:views/templates/film_synopses_result_bloc.pt'}
    name = renamer()
    picture = CompositeUniqueProperty('picture')
    author = SharedUniqueProperty('author', 'contents')
    artists = SharedMultipleProperty('artists', 'creations')
    directors = SharedMultipleProperty('directors', 'productions')

    def __init__(self, **kwargs):
        self._presentation_text = None
        super(FilmSynopses, self).__init__(**kwargs)
        self.set_data(kwargs)

    def _init_presentation_text(self):
        self._presentation_text = html_to_text(
            getattr(self, 'abstract', ''))

    def __setattr__(self, name, value):
        super(FilmSynopses, self).__setattr__(name, value)
        if name == 'abstract':
            self._init_presentation_text()

    @property
    def artists_ids(self):
        return [str(get_oid(a)) for a in self.artists]

    @property
    def directors_ids(self):
        return [str(get_oid(a)) for a in self.directors]

    @property
    def relevant_data(self):
        result = super(FilmSynopses, self).relevant_data
        result.extend([', '.join([a.title for a in self.directors]),
                       ', '.join([a.title for a in self.artists])])
        return result

    def presentation_text(self, nb_characters=400):
        text = getattr(self, '_presentation_text', None)
        if text is None:
            self._init_presentation_text()
            text = getattr(self, '_presentation_text', '')

        return text[:nb_characters]+'...'
Ejemplo n.º 4
0
class CinemaReview(BaseReview):
    """Review class"""

    type_title = _('Cinema review')
    icon = 'lac-icon icon-reviwe-cinema'
    templates = {
        'default': 'lac:views/templates/review_result.pt',
        'bloc': 'lac:views/templates/review_result_bloc.pt'
    }
    name = renamer()
    directors = SharedMultipleProperty('directors', 'productions')

    @property
    def appreciation_title(self):
        return APPRECIATIONS.get(getattr(self, 'appreciation', ''), '')

    @property
    def directors_ids(self):
        return [str(get_oid(a)) for a in self.directors]

    @property
    def relevant_data(self):
        result = super(CinemaReview, self).relevant_data
        result.extend([', '.join([a.title for a in self.directors])])
        return result
Ejemplo n.º 5
0
class User(OriginUser, Entity):

    groups = SharedMultipleProperty('groups', 'members')

    def __init__(self,
                 password=None,
                 email=None,
                 tzname=None,
                 locale=None,
                 **kwargs):
        OriginUser.__init__(self, password, email, tzname, locale)
        Entity.__init__(self, **kwargs)

    def email_password_reset(self, request, message=None):
        """ Sends a password reset email."""
        root = request.virtual_root
        sitename = acquire(root, 'title', None) or 'Dace'
        principals = find_service(self, 'principals')
        reset = principals.add_reset(self)
        # XXX should this really point at an SDI URL?
        reseturl = request.resource_url(reset)
        if not self.email:
            raise ValueError('User does not possess a valid email address.')

        _message = message
        if _message is None:
            _message = Message(
                subject='Account information for %s' % sitename,
                recipients=[self.email],
                body=render(
                    'dace:objectofcollaboration/principal/templates/resetpassword_email.pt',
                    dict(reseturl=reseturl)))
        mailer = get_mailer(request)
        mailer.send(_message)
Ejemplo n.º 6
0
class Correlation(Debatable):
    """Correlation class"""
    name = renamer()
    source = SharedUniqueProperty('source', 'source_correlations')
    targets = SharedMultipleProperty('targets', 'target_correlations')
    context = SharedUniqueProperty('context', 'contextualized_correlations')
    author = SharedUniqueProperty('author')
    channels = CompositeMultipleProperty('channels', 'subject')
    comments = CompositeMultipleProperty('comments')

    def __init__(self, **kwargs):
        super(Correlation, self).__init__(**kwargs)
        self.set_data(kwargs)
        self.type = CorrelationType.weak
        self.tags = PersistentList()
        # self.addtoproperty('channels', Channel(title=_("General")))

    @property
    def ends(self):
        """Return the ends of the correlation"""
        result = list(self.targets)
        result.append(self.source)
        return result

    @property
    def channel(self):
        channels = getattr(self, 'channels', [])
        return channels[0] if channels else None

    @property
    def type_name(self):
        return CorrelationType.type_name(self.type)
Ejemplo n.º 7
0
class Object1(Object):
    composition_u = CompositeUniqueProperty('composition_u', 'shared2_u',
                                            False)
    composition_m = CompositeMultipleProperty('composition_m', 'shared21_u',
                                              False)
    shared_u = SharedUniqueProperty('shared_u', 'shared22_u', False)
    shared_m = SharedMultipleProperty('shared_m', 'shared23_u', False)
Ejemplo n.º 8
0
class Keyword(VisualisableElement, Entity):
    """Keyword class"""

    name = renamer()
    referenced_elements = SharedMultipleProperty('referenced_elements',
                                                 'keywords')

    def __init__(self, **kwargs):
        super(Keyword, self).__init__(**kwargs)
        self.set_data(kwargs)
Ejemplo n.º 9
0
class FlowNode(BPMNElement):

    incoming = SharedMultipleProperty('incoming', 'target', False)
    outgoing = SharedMultipleProperty('outgoing', 'source', False)
    workitems = CompositeMultipleProperty('workitems', None, False)
    process = SharedUniqueProperty('process', 'nodes', False)

    def __init__(self, definition, **kwargs):
        super(FlowNode,self).__init__( definition, **kwargs)

    def prepare(self):
        registry = get_current_registry()
        registry.notify(ActivityPrepared(self))

    def __call__(self, transaction):
        self.start(transaction)

    def find_executable_paths(self, source_path, source):
        pass# pragma: no cover

    def start(self, transaction):
        raise NotImplementedError# pragma: no cover

    def play(self, transitions):
        registry = get_current_registry()
        registry.notify(ActivityFinished(self))
        self.process.play_transitions(self, transitions)

    def replay_path(self, decision, transaction):
        pass# pragma: no cover

    def stop(self):
        pass# pragma: no cover

    @property
    def definition(self):
        return self.process.definition[self.__name__]

    def __repr__(self):# pragma: no cover
        return "%s(%r)" % (
            self.__class__.__name__,
            self.id
            )
Ejemplo n.º 10
0
class ParticipativeEntity(Entity):
    """ A Participative entity is an entity that can be improved"""

    contributors = SharedMultipleProperty('contributors', 'contributions')

    def add_contributors(self, contributors):
        for contributor in contributors:
            if contributor not in self.contributors:
                self.addtoproperty('contributors', contributor)

    def replace_by(self, source):
        pass
Ejemplo n.º 11
0
class Group(Entity):

    members = SharedMultipleProperty('members', 'groups')

    def __init__(self, **kwargs):
        super(Group, self).__init__(**kwargs)
        self.set_data(kwargs)

    def reindex(self):
        super(Group, self).reindex()
        for member in self.members:
            member.reindex()
Ejemplo n.º 12
0
class ServiceableEntity(Entity):

    services = SharedMultipleProperty('services', 'perimeter')

    def __init__(self, **kwargs):
        super(ServiceableEntity, self).__init__(**kwargs)

    def get_services(self, kind=None, user=None):
        services = self.services
        if user:
            services = [s for s in self.services if
                        can_access(user, s)]

        if not services or kind is None:
            return services

        # registry_content = get_current_registry().content
        return [s for s in services if s.definition.service_id == kind]

    def get_all_services(self, context=None, user=None,
                         site=None, kinds=None,
                         validate=True, delegation=True):
        if user is None:
            user = get_current()

        if site is None:
            site = get_site_folder(True)

        if context is None:
            context = self

        if kinds is None:
            kinds = SERVICES

        services = {}
        for service in kinds:
            services[service] = self.get_services(service)

        result = {}
        for service, items in services.items():
            result[service] = []
            for item in items:
                if context is item.perimeter and \
                   (not validate or (validate and item.is_valid(context, user))) \
                   and (not delegation or (delegation and item.delegated_to(user))):
                    result[service].append(item)

            result[service] = list(set(result[service]))

        return {service: value for service, value in result.items() if value}
Ejemplo n.º 13
0
class FlowNodeDefinition(BPMNElementDefinition):

    incoming = SharedMultipleProperty('incoming', 'target', False)
    outgoing = SharedMultipleProperty('outgoing', 'source', False)
    process = SharedUniqueProperty('process', 'nodes', False)
    factory = Attribute("factory")

    def create(self):
        return self.factory(self)

    def __init__(self, **kwargs):
        super(FlowNodeDefinition, self).__init__(**kwargs)
        self.groups = []
        if 'groups' in kwargs:
            self.groups = kwargs['groups']

    def find_startable_paths(self, source_path, source):
        decision_path = source_path.clone()
        source_transaction = source_path.transaction.__parent__
        source_transaction.remove_subtransaction(source_path.transaction)
        yield decision_path

    def __repr__(self):  # pragma: no cover
        return "<%s %r>" % (self.__class__.__name__, self.__name__)
Ejemplo n.º 14
0
class BaseReview(VisualisableElement, SearchableEntity):
    """Base Review class"""

    type_title = _('Base review')
    thumbnail = CompositeUniqueProperty('thumbnail')
    picture = CompositeUniqueProperty('picture')
    author = SharedUniqueProperty('author', 'contents')
    artists = SharedMultipleProperty('artists', 'creations')

    def __init__(self, **kwargs):
        self._presentation_text = None
        super(BaseReview, self).__init__(**kwargs)
        self.set_data(kwargs)

    def _init_presentation_text(self):
        self._presentation_text = html_article_to_text(
            getattr(self, 'article', ''))

    def __setattr__(self, name, value):
        super(BaseReview, self).__setattr__(name, value)
        if name == 'article':
            self._init_presentation_text()

    @property
    def relevant_data(self):
        result = super(BaseReview, self).relevant_data
        result.extend([', '.join([a.title for a in self.artists])])
        return result

    @property
    def artists_ids(self):
        return [str(get_oid(a)) for a in self.artists]

    def presentation_text(self, nb_characters=400):
        text = getattr(self, '_presentation_text', None)
        if text is None:
            self._init_presentation_text()
            text = getattr(self, '_presentation_text', '')

        return text[:nb_characters]+'...'

    def get_visibility_filter(self):
        result = super(BaseReview, self).get_visibility_filter()
        authors = [self.author] if self.author else []
        result.update({
            'contribution_filter': {'authors': authors}})
        return result
Ejemplo n.º 15
0
class Preregistration(VisualisableElement, Entity):
    """Preregistration class"""
    icon = 'typcn typcn-user-add'
    templates = {
        'default': 'novaideo:views/templates/preregistration_result.pt',
        'bloc': 'novaideo:views/templates/preregistration_result.pt'
    }
    name = renamer()
    ballots = CompositeMultipleProperty('ballots')
    ballot_processes = SharedMultipleProperty('ballot_processes')
    organization = SharedUniqueProperty('organization')

    def __init__(self, **kwargs):
        super(Preregistration, self).__init__(**kwargs)
        initial_password = kwargs.pop('password', None)
        if initial_password:
            initial_password = User.pwd_manager.encode(initial_password)

        self.initial_password = initial_password
        self.set_data(kwargs)
        self.title = self.first_name + ' ' + \
                     self.last_name

    def init_deadline(self, date):
        self.deadline_date = date\
            + datetime.timedelta(seconds=DEADLINE_PREREGISTRATION)
        return self.deadline_date

    def get_deadline_date(self):
        if getattr(self, 'deadline_date', None) is not None:
            return self.deadline_date

        self.deadline_date = self.created_at\
            + datetime.timedelta(seconds=DEADLINE_PREREGISTRATION)
        return self.deadline_date

    def has_trusted_email(self, trusted_emails):
        email = getattr(self, 'email', None)
        if email and trusted_emails:
            return any(email.find(t) >= 0 for t in trusted_emails)

        return True

    @property
    def is_expired(self):
        return datetime.datetime.now(tz=pytz.UTC) > self.get_deadline_date()
Ejemplo n.º 16
0
class Organization(VisualisableElement, Group):
    """Organization class"""

    templates = {
        'default': 'novaideo:views/templates/organization_result.pt',
        'popover': 'novaideo:views/templates/organization_popover.pt',
        'small': 'novaideo:views/templates/small_organization_result.pt',
        'header': 'novaideo:views/templates/organization_header.pt',
    }
    icon = 'glyphicon glyphicon-home'
    name = renamer()
    managers = managers()
    members = SharedMultipleProperty('members', 'organization')
    logo = CompositeUniqueProperty('logo')
    cover_picture = CompositeUniqueProperty('cover_picture')

    def __init__(self, **kwargs):
        super(Organization, self).__init__(**kwargs)
        self.set_data(kwargs)
Ejemplo n.º 17
0
class Order(VisualisableElement, Entity):
    """Order class"""

    name = renamer()
    icon = 'glyphicon glyphicon-barcode'
    templates = {
        'default': 'lac:views/templates/order_result.pt',
        'bloc': 'lac:views/templates/order_result.pt'
    }
    products = SharedMultipleProperty('products', 'order')
    customeraccount = SharedUniqueProperty('customeraccount', 'orders')

    def __init__(self, **kwargs):
        super(Order, self).__init__(**kwargs)
        self.set_data(kwargs)

    @property
    def total(self):
        return sum([float(product.get_price()) for product in self.products])
Ejemplo n.º 18
0
class Channel(Commentable):
    """Channel class"""

    type_title = _('Channel')
    icon = 'icon novaideo-icon icon-idea'
    templates = {'default': 'novaideo:views/templates/channel_result.pt'}
    name = renamer()
    members = SharedMultipleProperty('members', 'following_channels')
    subject = SharedUniqueProperty('subject', 'channels')

    def __init__(self, **kwargs):
        super(Channel, self).__init__(**kwargs)
        self.set_data(kwargs)
        self._comments_at = OOBTree()

    def add_comment(self, comment):
        self._comments_at[comment.created_at] = get_oid(comment)

    def remove_comment(self, comment):
        self._comments_at.pop(comment.created_at)

    def get_comments_between(self, start, end):
        return list(self._comments_at.values(min=start, max=end))

    def get_subject(self, user=None):
        subject = self.subject
        return subject if subject else getattr(self, '__parent__', None)

    def get_title(self, user=None):
        title = getattr(self, 'title', '')
        if not title:
            return getattr(self.get_subject(user), 'title', None)

        return title

    def is_discuss(self):
        return self.subject.__class__.__name__.lower() == 'person'
Ejemplo n.º 19
0
class Amendment(CorrelableEntity, SearchableEntity, DuplicableEntity,
                PresentableEntity, Debatable):
    """Amendment class"""

    type_title = _('Amendment')
    icon = 'icon novaideo-icon icon-amendment'
    name = renamer()
    templates = {
        'default': 'novaideo:views/templates/amendment_result.pt',
        'popover': 'novaideo:views/templates/amendment_popover.pt',
        'bloc': 'novaideo:views/templates/amendment_bloc.pt'
    }
    author = SharedUniqueProperty('author')
    proposal = SharedUniqueProperty('proposal', 'amendments')
    attached_files = SharedMultipleProperty('attached_files')

    def __init__(self, **kwargs):
        super(Amendment, self).__init__(**kwargs)
        self.explanations = PersistentDict()
        self.set_data(kwargs)
        self.addtoproperty('channels', Channel())

    @property
    def is_published(self):
        return 'submitted' in self.state

    @property
    def working_group(self):
        return self.proposal.working_group

    @property
    def authors(self):
        return [self.author]

    @property
    def challenge(self):
        return getattr(self.proposal, 'challenge', None)

    def _init_presentation_text(self):
        self._presentation_text = html_to_text(getattr(self, 'text', ''))

    def __setattr__(self, name, value):
        super(Amendment, self).__setattr__(name, value)
        if name == 'text':
            self._init_presentation_text()

    def presentation_text(self, nb_characters=400):
        text = getattr(self, '_presentation_text', None)
        if text is None:
            self._init_presentation_text()
            text = getattr(self, '_presentation_text', '')

        return truncate_text(text, nb_characters)

# @region.cache_on_arguments()

    def get_used_ideas(self):
        """Return used ideas"""

        result = []
        if not hasattr(self, 'explanations'):
            return result

        for explanation in self.explanations.values():
            if explanation['intention'] is not None:
                try:
                    result.extend(
                        Intention.get_explanation_ideas(
                            explanation['intention']))
                except Exception:
                    pass

        return list(set(result))

    @property
    def related_ideas(self):
        """Return added ideas"""

        result = []
        for explanation in self.explanations.values():
            if explanation['intention'] is not None:
                try:
                    result.extend(
                        Intention.get_explanation_data(
                            explanation['intention'])['related_ideas'])
                except Exception:
                    pass

        return list(set(result))
Ejemplo n.º 20
0
class Challenge(SearchableEntity, CorrelableEntity, PresentableEntity,
                ExaminableEntity, Node, Emojiable, SignalableEntity,
                Debatable):
    """Challenge class"""
    type_title = _('Challenge')
    icon = 'ion-trophy'
    templates = {
        'default': 'novaideo:views/templates/challenge_result.pt',
        'bloc': 'novaideo:views/templates/challenge_card.pt',
        'small': 'novaideo:views/templates/small_challenge_result.pt',
        'popover': 'novaideo:views/templates/challenge_popover.pt',
        'card': 'novaideo:views/templates/challenge_card.pt'
    }
    name = renamer()
    author = SharedUniqueProperty('author', 'challenges')
    image = CompositeUniqueProperty('image')
    proposals = SharedMultipleProperty('proposals', 'challenge')
    ideas = SharedMultipleProperty('ideas', 'challenge')
    questions = SharedMultipleProperty('questions', 'challenge')
    attached_files = CompositeMultipleProperty('attached_files')
    invited_users = SharedMultipleProperty('invited_users')
    url_files = CompositeMultipleProperty('url_files')

    def __init__(self, **kwargs):
        super(Challenge, self).__init__(**kwargs)
        self.set_data(kwargs)
        self.addtoproperty('channels', Channel())
        self.urls = PersistentDict({})

    def __setattr__(self, name, value):
        super(Challenge, self).__setattr__(name, value)
        if name in ('deadline', 'published_at', 'created_at') and value:
            self.init_total_days()

    @property
    def related_contents(self):
        return [content[0] for content in self.all_related_contents]

    @property
    def challenge(self):
        return self

    @property
    def transformed_from(self):
        """Return all related contents"""
        transformed_from = [
            correlation[1].context
            for correlation in self.get_related_contents(
                CorrelationType.solid, ['transformation'])
            if correlation[1].context
        ]
        return transformed_from[0] if transformed_from else None

    @property
    def is_expired(self):
        if 'closed' in self.state:
            return True

        deadline = getattr(self, 'deadline', None)
        if deadline is not None:
            now = datetime.datetime.now(tz=pytz.UTC)
            return now.date() >= deadline

        return False

    @property
    def can_add_content(self):
        return not self.is_expired and 'pending' in self.state

    @property
    def remaining_duration(self):
        deadline = getattr(self, 'deadline', None)
        duration = getattr(self, 'duration', None)
        if deadline is not None and duration is not None:
            now = datetime.datetime.now(tz=pytz.UTC)
            remaining = (deadline - now.date()).days
            return remaining if remaining >= 0 else 0

        return None

    def init_published_at(self):
        setattr(self, 'published_at', datetime.datetime.now(tz=pytz.UTC))

    def init_support_history(self):
        if not hasattr(self, '_support_history'):
            setattr(self, '_support_history', PersistentList())

    def init_total_days(self):
        deadline = getattr(self, 'deadline', None)
        date = getattr(self, 'published_at', None)
        date = date if date else getattr(self, 'created_at', None)
        if deadline is not None and date is not None:
            duration = (deadline - date.date()).days
            setattr(self, 'duration', duration)

    def is_managed(self, root):
        return root.manage_challenges

    def get_attached_files_data(self):
        return get_files_data(self.attached_files)

    def get_all_attached_files_data(self):
        files = list(self.attached_files)
        files.append(self.image)
        return get_files_data(files)

    def get_node_descriminator(self):
        return 'challenge'

    def format(self, request):
        text = getattr(self, 'text', '')
        all_urls, url_files, text_urls, formatted_text = text_urls_format(
            text, request, True)
        self.urls = PersistentDict(all_urls)
        self.setproperty('url_files', url_files)
        self.formatted_text = formatted_text
        self.formatted_urls = text_urls
Ejemplo n.º 21
0
class WorkingGroup(VisualisableElement, Entity):
    """Working group class"""

    name = renamer()
    template = 'pontus:templates/visualisable_templates/object.pt'
    proposal = SharedUniqueProperty('proposal', 'working_group')
    members = SharedMultipleProperty('members', 'working_groups')
    wating_list = SharedMultipleProperty('wating_list')
    ballots = CompositeMultipleProperty('ballots')
    improvement_cycle_proc = SharedUniqueProperty('improvement_cycle_proc')
    workspace = CompositeUniqueProperty('workspace', 'working_group')

    def init_workspace(self):
        self.addtoproperty('workspace', Workspace(title="Workspace"))

    @property
    def work_mode(self):
        mode_id = getattr(self, 'work_mode_id', None)
        if mode_id:
            return WORK_MODES.get(mode_id, None)

        root = self.__parent__
        if hasattr(root, 'get_work_modes') and len(root.get_work_modes()) == 1:
            return root.get_default_work_mode()

        return None

    @property
    def challenge(self):
        return getattr(self.proposal, 'challenge', None)

    def get_state(self, request, user):
        return get_states_mapping(user, self,
                                  getattr(self, 'state_or_none', [None])[0])

    def empty(self, remove_author=True):
        author = self.proposal.author
        self.state = PersistentList(['deactivated'])
        self.setproperty('wating_list', [])
        if hasattr(self, 'first_improvement_cycle'):
            del self.first_improvement_cycle

        if hasattr(self, 'first_vote'):
            del self.first_vote

        members = self.members
        if remove_author and author in members:
            members.remove(author)

        for member in members:
            self.delfromproperty('members', member)
            revoke_roles(member, (('Participant', self.proposal), ))

        self.init_nonproductive_cycle()

    def inc_iteration(self):
        self.iteration = getattr(self, 'iteration', 0) + 1

    def init_nonproductive_cycle(self):
        self.nonproductive_cycle = 0

    def inc_nonproductive_cycle(self):
        self.nonproductive_cycle = getattr(self, 'nonproductive_cycle', 0) + 1

    def is_member(self, user):
        mask = getattr(user, 'mask', None)
        return user in self.members or (mask and mask in self.members)

    def in_wating_list(self, user):
        mask = getattr(user, 'mask', None)
        return user in self.wating_list or (mask and mask in self.wating_list)

    def get_member(self, user):
        if not self.is_member(user):
            return None

        if user in self.members:
            return user

        mask = getattr(user, 'mask', None)
        if mask and mask in self.members:
            return mask

        return None

    def get_member_in_wating_list(self, user):
        if not self.in_wating_list(user):
            return None

        if user in self.wating_list:
            return user

        mask = getattr(user, 'mask', None)
        if mask and mask in self.wating_list:
            return mask

        return None
Ejemplo n.º 22
0
class DuplicableEntity(Entity):
    """ A Duplicable entity is an entity that can be duplicated"""

    originalentity = SharedUniqueProperty('originalentity', 'duplicates')
    duplicates = SharedMultipleProperty('duplicates', 'originalentity')
Ejemplo n.º 23
0
class Alert(VisualisableElement, Entity):
    """Alert class"""
    users_to_alert = SharedMultipleProperty('users_to_alert')
    subjects = SharedMultipleProperty('subjects')

    def __init__(self, kind, **kwargs):
        super(Alert, self).__init__(**kwargs)
        self.set_data(kwargs)
        self.kind = kind
        self.users_toalert = OOBTree()
        self.users_toexclude = OOBTree()

    @property
    def pattern(self):
        return INTERNAL_ALERTS.get(self.kind, None)

    @property
    def templates(self):
        return self.pattern.templates

    @property
    def icon(self):
        return self.pattern.get_icon(self)

    def init_alert(self, users, subjects=[], exclude=[]):
        self.subscribe(users)
        for subject in subjects:
            self.addtoproperty('subjects', subject)

        self.exclude(exclude)

    def subscribe(self, users):
        if not isinstance(users, (list, tuple, set)):
            users = [users]

        for user in users:
            oid = get_oid(user, user)
            self.users_toalert[str(oid)] = oid

    def unsubscribe(self, user):
        key = str(get_oid(user, user))
        if key in self.users_toalert:
            self.users_toalert.pop(key)

        user.addtoproperty('old_alerts', self)
        self.reindex()

    def exclude(self, users):
        if not isinstance(users, (list, tuple, set)):
            users = [users]

        for user in users:
            oid = get_oid(user, user)
            self.users_toexclude[str(oid)] = oid

    def is_to_alert(self, user):
        key = str(get_oid(user, user))
        # TODO self not in user.old_alerts
        return key in self.users_toalert and \
            key not in self.users_toexclude

    def get_subject_state(self, subject, user, last_state=False):
        states = getattr(subject, 'state_or_none', [None])
        state = states[0]
        if last_state:
            state = states[-1]

        return get_states_mapping(
            user, subject, state)

    def render(self, template, current_user, request):
        layout_manager = getattr(request, 'layout_manager', None)
        layout = layout_manager.layout if layout_manager \
            else GlobalLayout(None, request)
        render_dict = {
            'object': self,
            'current_user': current_user,
            'layout': layout
        }
        return renderers.render(
            self.templates[template],
            render_dict,
            request)

    def is_kind_of(self, kind):
        return kind == self.kind

    def has_args(self, **kwargs):
        for key in kwargs:
            if getattr(self, key, None) != kwargs[key]:
                return False

        return True
Ejemplo n.º 24
0
class Comment(Commentable, CorrelableEntity, Emojiable, SignalableEntity):
    """Comment class"""
    icon = 'icon ion-chatbubbles'
    templates = {'default': 'novaideo:views/templates/comment_result.pt'}
    name = renamer()
    author = SharedUniqueProperty('author')
    files = CompositeMultipleProperty('files')
    url_files = CompositeMultipleProperty('url_files')
    related_correlation = SharedUniqueProperty('related_correlation',
                                               'targets')
    contextualized_correlations = SharedMultipleProperty(
        'contextualized_correlations', 'context')

    def __init__(self, **kwargs):
        super(Comment, self).__init__(**kwargs)
        self.set_data(kwargs)
        self.urls = PersistentDict({})
        self.edited = False
        self.pinned = False

    @property
    def channel(self):
        """Return the channel of th commented entity"""

        if not isinstance(self.__parent__, Comment):
            return self.__parent__
        else:
            return self.__parent__.channel

    @property
    def root(self):
        """Return the root comment"""

        if not isinstance(self.__parent__, Comment):
            return self
        else:
            return self.__parent__.root

    @property
    def comment_parent(self):
        """Return the root comment"""

        if isinstance(self.__parent__, Comment):
            return self.__parent__
        else:
            return None

    @property
    def subject(self):
        """Return the commented entity"""
        return self.channel.get_subject()

    @property
    def challenge(self):
        return getattr(self.subject, 'challenge', None)

    @property
    def relevant_data(self):
        return [
            getattr(self, 'comment', ''),
            getattr(self.author, 'title', getattr(self.author, '__name__', ''))
        ]

    @property
    def related_contents(self):
        subject = self.subject
        return [
            content[0] for content in self.contextualized_contents
            if content[0] is not subject
        ]

    @property
    def associated_contents(self):
        subject = self.subject
        return [
            content[0] for content in self.contextualized_contents if
            content[0] is not subject and not getattr(content[1], 'tags', [])
        ]

    def set_associated_contents(self, associated_contents, user):
        subject = self.subject
        current_associated_contents = self.associated_contents
        associated_contents_to_add = [
            i for i in associated_contents
            if i not in current_associated_contents
        ]
        associated_contents_to_del = [
            i for i in current_associated_contents
            if i not in associated_contents
            and i not in associated_contents_to_add
        ]
        correlations = connect(
            subject,
            associated_contents_to_add,
            {
                'comment': _('Add related contents'),
                'type': _('Edit the comment')
            },
            author=user,
        )
        for correlation in correlations:
            correlation.setproperty('context', self)

        disconnect(subject, associated_contents_to_del)

    def get_title(self):
        return self.subject.title

    def presentation_text(self, nb_characters=400):
        return getattr(self, 'comment', "")[:nb_characters] + '...'

    def get_discuss_url(self, request, user):
        subject = self.channel.get_subject(user)
        return request.resource_url(subject, "@@index") + '#comment-' + str(
            get_oid(self, 'None'))

    def get_url(self, request):
        return request.resource_url(request.root,
                                    "@@seecomment",
                                    query={'comment_id': get_oid(self)})

    def get_related_contents(self, user):
        return [r for r in self.related_contents if can_access(user, r)]

    def format(self, request, is_html=False):
        comment = getattr(self, 'comment', '')
        all_urls, url_files, text_urls, formatted_text = text_urls_format(
            comment, request, is_html)
        self.urls = PersistentDict(all_urls)
        self.setproperty('url_files', url_files)
        self.formatted_comment = formatted_text
        self.formatted_urls = text_urls

    def get_attached_files_data(self):
        return get_files_data(self.files)

    def can_add_reaction(self, user, process):
        return True
Ejemplo n.º 25
0
class SearchableEntity(ServiceableEntity):
    """ A Searchable entity is an entity that can be searched"""

    icon = 'glyphicon glyphicon-question-sign'
    templates = {'default': 'lac:views/templates/default_result.pt',
                 'bloc': 'lac:views/templates/default_result_bloc.pt',
                 'extraction': 'lac:views/templates/extraction/default_result.pt'}
    tree = synchronize_tree()
    type_title = ''
    files = CompositeMultipleProperty('files')
    connections_from = SharedMultipleProperty(
        'connections_from', 'connections_to')
    connections_to = SharedMultipleProperty(
        'connections_to', 'connections_from')
    visibility_dates = dates('visibility_dates')
    labels = SharedMultipleProperty('labels')

    def __init__(self, **kwargs):
        super(SearchableEntity, self).__init__(**kwargs)
        self._tree = PersistentDict()
        self.keywords = PersistentList()
        self.set_data(kwargs)
        self.source_site = get_oid(get_site_folder(True),
                                   None)
        self._keywords_ = []
        self._init_keywords()

    def __setattr__(self, name, value):
        super(SearchableEntity, self).__setattr__(name, value)
        if name == 'description':
            self._init_presentation_text()

    @property
    def object_labels(self):
        return {'labels': self.labels}

    @property
    def metadata(self):
        return self.get_data(omit(MetadataSchema(),
                                 '_csrf_token_'))

    @property
    def is_published(self):
        return 'published' in self.state

    @property
    def object_id(self):
        source_data = getattr(self, 'source_data', {})
        obj_id = source_data.get('id', '') + '_' +\
            source_data.get('source_id', '')
        if obj_id == '_':
            obj_id = str(getattr(self, '__oid__', None))+'_lac'

        return obj_id

    @property
    def json_tree(self):
        return json.dumps(dict(self.tree))

    @property
    def is_imported(self):
        source_id = getattr(self, 'source_data', {}).get('source_id', None)
        return True if source_id and source_id in list(IMPORT_SOURCES.keys())\
               else False

    @property
    def relevant_data(self):
        return [getattr(self, 'title', ''),
                getattr(self, 'description', ''),
                ', '.join(self.keywords)]

    @property
    def sections(self):
        tree = dict(self.get_normalized_tree())
        levels = get_keywords_by_level(tree, ROOT_TREE)
        if len(levels) >= 2:
            return sorted(levels[1])

        return []

    @property
    def substitutions(self):
        return [self]

    def _init_presentation_text(self):
        pass

    def _init_keywords(self):
        pass

    def get_all_keywords(self):
        return self.keywords

    def get_more_contents_criteria(self):
        "return specific query, filter values"
        keywords = list(self.keywords)
        root_tree = ROOT_TREE.lower()
        if root_tree in keywords:
            keywords.remove(root_tree)

        return None, {'keywords': keywords}

    def get_release_date(self):
        return getattr(self, 'release_date', self.modified_at)

    def presentation_text(self, nb_characters=400):
        return getattr(self, 'description', "")[:nb_characters]+'...'

    def get_normalized_tree(self, type_='out'):
        site = get_site_folder(True)
        return site.get_normalized_tree(getattr(self, 'tree', {}), type_)

    def get_visibility_filter(self):
        registry = get_current_registry()
        return {
            'metadata_filter': {
                'tree': deepcopy(self.tree),
                'content_types': [registry.content.typeof(self)],
                'states': list(getattr(self, 'state', []))
            }
        }

    def set_metadata(self, appstruct):
        if 'site' not in appstruct:
            site = get_site_folder(True)

        if 'accessibility' in appstruct:
            object_set_access_control(appstruct.get('accessibility'), self, site)
            appstruct.pop('accessibility')

        data = {}
        for key in MetadataSchema():
            name = key.name
            if name in appstruct:
                data[name] = appstruct.pop(name)

        if 'object_labels' in data:
            new_labels = [label['_object_data'] for label
                          in data['object_labels']['new_labels']]
            all_labels = []
            if new_labels:
                root = site.__parent__
                for label in new_labels:
                    root.addtoproperty('labels', label)
                    all_labels.append(label)

            all_labels.extend(data['object_labels']['labels'])
            data['labels'] = all_labels
            data.pop('object_labels')

        self.set_data(data)
        self.release_date = getattr(
            self, 'release_date', self.created_at).replace(
            tzinfo=pytz.UTC)

    def labels_data(self, site):
        labels = getattr(self, 'labels', [])
        labels_data = [{'title': l.title,
                        'img': l.picture.url} for l in labels]
        site_oid = get_oid(site)
        if site_oid != self.source_site:
            orig_site = get_obj(self.source_site)
            if orig_site.favicon:
                labels_data.append({'title': orig_site.title,
                                    'img': orig_site.favicon.url})

        return labels_data
Ejemplo n.º 26
0
class DuplicableEntity(Entity):
    """ A Duplicable entity is an entity that can be duplicated"""

    original = SharedUniqueProperty('original', 'branches')
    branches = SharedMultipleProperty('branches', 'original')
Ejemplo n.º 27
0
class Person(User, SearchableEntity, CorrelableEntity, Debatable):
    """Person class"""

    type_title = _('Person')
    icon = 'icon glyphicon glyphicon-user'  #'icon novaideo-icon icon-user'
    templates = {
        'default': 'novaideo:views/templates/person_result.pt',
        'bloc': 'novaideo:views/templates/person_bloc.pt',
        'small': 'novaideo:views/templates/small_person_result.pt',
        'popover': 'novaideo:views/templates/person_popover.pt',
        'card': 'novaideo:views/templates/person_card.pt',
        'header': 'novaideo:views/templates/person_header.pt',
    }
    default_picture = 'novaideo:static/images/user100.png'
    name = renamer()
    tokens = CompositeMultipleProperty('tokens')
    tokens_ref = SharedMultipleProperty('tokens_ref')
    organization = SharedUniqueProperty('organization', 'members')
    events = SharedMultipleProperty('events', 'author')
    picture = CompositeUniqueProperty('picture')
    cover_picture = CompositeUniqueProperty('cover_picture')
    ideas = SharedMultipleProperty('ideas', 'author')
    selections = SharedMultipleProperty('selections')
    working_groups = SharedMultipleProperty('working_groups', 'members')
    wg_participations = SharedMultipleProperty('wg_participations',
                                               'wating_list_participation')
    old_alerts = SharedMultipleProperty('old_alerts')
    following_channels = SharedMultipleProperty('following_channels',
                                                'members')
    folders = SharedMultipleProperty('folders', 'author')
    questions = SharedMultipleProperty('questions', 'author')
    challenges = SharedMultipleProperty('challenges', 'author')
    ballots = CompositeMultipleProperty('ballots')
    mask = SharedUniqueProperty('mask', 'member')

    def __init__(self, **kwargs):
        self.branches = PersistentList()
        self.keywords = PersistentList()
        super(Person, self).__init__(**kwargs)
        kwargs.pop('password', None)
        self.set_data(kwargs)
        self.set_title()
        self.last_connection = datetime.datetime.now(tz=pytz.UTC)
        self._read_at = OOBTree()
        self.guide_tour_data = PersistentDict({})
        self.confidence_index = 0
        self._notes = OOBTree()
        self.allocated_tokens = OOBTree()
        self.len_allocated_tokens = PersistentDict({})
        self.reserved_tokens = PersistentList([])
        self._submited_at = OOBTree()
        self._reported_at = OOBTree()

    def __setattr__(self, name, value):
        super(Person, self).__setattr__(name, value)
        if name == 'organization' and value:
            self.init_contents_organizations()

    def get_len_tokens(self, root=None, exclude_reserved_tokens=False):
        root = root or getSite()
        return root.tokens_mini if exclude_reserved_tokens \
            else root.tokens_mini + len(self.reserved_tokens)

    def get_len_evaluations(self, exclude_reserved_tokens=False):
        total = self.len_allocated_tokens.get(Evaluations.support, 0) + \
            self.len_allocated_tokens.get(Evaluations.oppose, 0)
        if exclude_reserved_tokens:
            return total - len([
                o for o in self.reserved_tokens if o in self.allocated_tokens
            ])
        return total

    def get_len_free_tokens(self, root=None, exclude_reserved_tokens=False):
        root = root or getSite()
        return self.get_len_tokens(root, exclude_reserved_tokens) - \
            self.get_len_evaluations(exclude_reserved_tokens)

    def has_token(self, obj=None, root=None):
        root = root or getSite()
        obj_oid = get_oid(obj, None)
        if obj_oid and obj_oid in self.reserved_tokens:
            return obj_oid not in self.allocated_tokens

        return self.get_len_free_tokens(root, True) > 0

    def add_token(self, obj, evaluation_type, root=None):
        if self.has_token(obj, root):
            self.allocated_tokens[get_oid(obj)] = evaluation_type
            self.len_allocated_tokens.setdefault(evaluation_type, 0)
            self.len_allocated_tokens[evaluation_type] += 1

    def remove_token(self, obj):
        obj_oid = get_oid(obj)
        if obj_oid in self.allocated_tokens:
            evaluation_type = self.allocated_tokens.pop(obj_oid)
            self.len_allocated_tokens.setdefault(evaluation_type, 0)
            self.len_allocated_tokens[evaluation_type] -= 1

    def add_reserved_token(self, obj):
        obj_oid = get_oid(obj)
        if obj_oid not in self.reserved_tokens:
            self.reserved_tokens.append(obj_oid)

    def remove_reserved_token(self, obj):
        obj_oid = get_oid(obj)
        if obj_oid in self.reserved_tokens:
            self.reserved_tokens.remove(obj_oid)

    def evaluated_objs(self, evaluation_type=None):
        if evaluation_type:
            return [
                get_obj(key) for value, key in self.allocated_tokens.byValue(
                    evaluation_type)
            ]

        return [get_obj(key) for key in self.allocated_tokens.keys()]

    def evaluated_objs_ids(self, evaluation_type=None):
        if evaluation_type:
            return [
                key for value, key in self.allocated_tokens.byValue(
                    evaluation_type)
            ]

        return list(self.allocated_tokens.keys())

    def init_contents_organizations(self):
        novaideo_catalog = find_catalog('novaideo')
        dace_catalog = find_catalog('dace')
        organizations_index = novaideo_catalog['organizations']
        object_authors_index = novaideo_catalog['object_authors']
        object_provides_index = dace_catalog['object_provides']
        query = object_authors_index.any([get_oid(self)]) & \
            object_provides_index.any(
                [Iidea.__identifier__, IProposal.__identifier__]) & \
            organizations_index.any([0])

        for entity in query.execute().all():
            entity.init_organization()
            entity.reindex()

    def set_read_date(self, channel, date):
        self._read_at[get_oid(channel)] = date

    def get_read_date(self, channel):
        return self._read_at.get(get_oid(channel),
                                 datetime.datetime.now(tz=pytz.UTC))

    def get_channel(self, user):
        all_channels = list(self.channels)
        all_channels.extend(list(getattr(user, 'channels', [])))
        for channel in all_channels:
            if user in channel.members and self in channel.members:
                return channel

        return None

    def addtoproperty(self, name, value, moving=None):
        super(Person, self).addtoproperty(name, value, moving)
        if name == 'selections':
            value.len_selections = getattr(value, 'len_selections', 0)
            value.len_selections += 1

    def delfromproperty(self, name, value, moving=None):
        super(Person, self).delfromproperty(name, value, moving)
        if name == 'selections':
            value.len_selections = getattr(value, 'len_selections', 0)
            if value.len_selections > 0:
                value.len_selections -= 1

    def set_title(self):
        if getattr(self, 'pseudonym', ''):
            self.title = self.pseudonym
        else:
            self.title = getattr(self, 'first_name', '') + ' ' + \
                getattr(self, 'last_name', '')

    def add_note(self, user, context, note, date, time_constant):
        self._notes[date] = (get_oid(user), get_oid(context), note)
        self.calculate_confidence_index(time_constant)

    def get_questions(self, user):
        if user is self:
            return self.questions + getattr(self.mask, 'questions', [])

        return self.questions

    def get_ideas(self, user):
        if user is self:
            return self.ideas + getattr(self.mask, 'ideas', [])

        return self.ideas

    def get_working_groups(self, user):
        if user is self:
            return self.working_groups + getattr(self.mask, 'working_groups',
                                                 [])

        return self.working_groups

    @property
    def proposals(self):
        return [wg.proposal for wg in self.working_groups]

    def get_proposals(self, user):
        if user is self:
            return self.proposals + getattr(self.mask, 'proposals', [])

        return self.proposals

    @property
    def contacts(self):
        return [s for s in self.selections if isinstance(s, Person)]

    @property
    def participations(self):
        result = [
            p for p in list(self.proposals) if any(s in p.state for s in [
                'amendable', 'open to a working group', 'votes for publishing',
                'votes for amendments'
            ])
        ]
        return result

    def get_participations(self, user):
        if user is self:
            return self.participations + getattr(self.mask, 'participations',
                                                 [])

        return self.participations

    @property
    def contents(self):
        result = [i for i in list(self.ideas) if i is i.current_version]
        result.extend(self.proposals)
        result.extend(self.questions)
        result.extend(self.challenges)
        result.extend(self.events)
        return result

    def get_contents(self, user):
        if user is self:
            return self.contents + getattr(self.mask, 'contents', [])

        return self.contents

    @property
    def active_working_groups(self):
        return [p.working_group for p in self.participations]

    def get_active_working_groups(self, user):
        if user is self:
            return self.active_working_groups + getattr(
                self.mask, 'active_working_groups', [])

        return self.active_working_groups

    def get_wg_participations(self, user):
        if user is self:
            return self.wg_participations + getattr(self.mask,
                                                    'wg_participations', [])

        return self.wg_participations

    @property
    def is_published(self):
        return 'active' in self.state

    @property
    def managed_organization(self):
        return get_objects_with_role(user=self, role='OrganizationResponsible')

    def get_confidence_index(self):
        return getattr(self, 'confidence_index', 0)

    def reindex(self):
        super(Person, self).reindex()
        root = getSite()
        self.__access_keys__ = PersistentList(generate_access_keys(self, root))

    def get_picture_url(self, kind, default):
        if self.picture:
            img = getattr(self.picture, kind, None)
            if img:
                return img.url

        return default

    def get_more_contents_criteria(self):
        "return specific query, filter values"
        return None, None

    def set_organization(self, organization):
        current_organization = self.organization
        if organization:
            if current_organization is not organization:
                is_manager = current_organization and has_role(
                    ('OrganizationResponsible', current_organization),
                    self,
                    ignore_superiors=True)
                if current_organization and is_manager:
                    revoke_roles(
                        self,
                        (('OrganizationResponsible', current_organization), ))

                self.setproperty('organization', organization)
        elif current_organization:
            is_manager = has_role(
                ('OrganizationResponsible', current_organization),
                self,
                ignore_superiors=True)
            if is_manager:
                revoke_roles(
                    self,
                    (('OrganizationResponsible', current_organization), ))

            self.delfromproperty('organization', current_organization)

    @property
    def all_alerts(self):
        novaideo_catalog = find_catalog('novaideo')
        dace_catalog = find_catalog('dace')
        alert_keys_index = novaideo_catalog['alert_keys']
        alert_exclude_keys_index = novaideo_catalog['alert_exclude_keys']
        object_provides_index = dace_catalog['object_provides']
        exclude = [str(get_oid(self))]
        if self.mask:
            exclude.append(str(get_oid(self.mask)))

        query = object_provides_index.any([IAlert.__identifier__]) & \
            alert_keys_index.any(self.get_alerts_keys()) & \
            alert_exclude_keys_index.notany(exclude)
        return query.execute()

    @property
    def alerts(self):
        old_alerts = [get_oid(a) for a in self.old_alerts]
        result = self.all_alerts

        def exclude(result_set, docids):
            filtered_ids = list(result_set.ids)
            for _id in docids:
                if _id in docids and _id in filtered_ids:
                    filtered_ids.remove(_id)

            return result_set.__class__(filtered_ids, len(filtered_ids),
                                        result_set.resolver)

        return exclude(result, old_alerts)

    def get_alerts_keys(self):
        result = ['all', str(get_oid(self))]
        if self.mask:
            result.append(str(get_oid(self.mask)))

        return result

    def get_alerts(self, alerts=None, kind=None, subject=None, **kwargs):
        if alerts is None:
            alerts = self.alerts

        if kind:
            alerts = [a for a in alerts if a.is_kind_of(kind)]

        if subject:
            alerts = [a for a in alerts if subject in a.subjects]

        if kwargs:
            alerts = [a for a in alerts if a.has_args(**kwargs)]

        return alerts

    def calculate_confidence_index(self, time_constant):
        now = datetime.datetime.utcnow().timestamp()
        notes = np.array([v[2] for v in self._notes.values()])
        dates = np.array([int(t.timestamp()) for t in self._notes.keys()])
        time_c = time_constant * 86400
        confidence_index = np.sum(
            np.dot(notes, np.exp(-np.log(2) * (now - dates) / time_c)))
        self.confidence_index = round(confidence_index, 1)

    @property
    def user_groups(self):
        groups = list(self.groups)
        if self.organization:
            groups.append(self.organization)

        if self.mask:
            groups.append(self.mask)

        return groups

    @property
    def user_locale(self):
        locale = getattr(self, 'locale', None)
        if not locale:
            locale = getSite(self).locale

        return locale

    def _init_mask(self, root):
        if not self.mask:
            mask = Mask()
            root.addtoproperty('masks', mask)
            self.setproperty('mask', mask)

    def get_mask(self, root=None):
        root = root if root else getSite()
        if not getattr(root, 'anonymisation', False):
            return self

        self._init_mask(root)
        return self.mask

    def add_submission(self, obj):
        now = datetime.datetime.now(tz=pytz.UTC)
        self._submited_at[now] = get_oid(obj)

    def add_report(self, obj):
        now = datetime.datetime.now(tz=pytz.UTC)
        self._reported_at[now] = get_oid(obj)

    def can_submit_idea(self, root=None):
        root = root if root else getSite()
        now = datetime.datetime.now(tz=pytz.UTC)
        monday = datetime.datetime.combine((now - datetime.timedelta(days=7)),
                                           datetime.time(0,
                                                         0,
                                                         0,
                                                         tzinfo=pytz.UTC))
        return len(self._submited_at.values(min=monday, max=now)) < getattr(
            root, 'nb_submission_maxi', 3)

    def can_report(self, root=None):
        root = root if root else getSite()
        now = datetime.datetime.now(tz=pytz.UTC)
        monday = datetime.datetime.combine((now - datetime.timedelta(days=7)),
                                           datetime.time(0,
                                                         0,
                                                         0,
                                                         tzinfo=pytz.UTC))
        return len(self._reported_at.values(min=monday, max=now)) < getattr(
            root, 'nb_reports_maxi', 3)
Ejemplo n.º 28
0
class Ballot(VisualisableElement, Entity):
    """Ballot class"""
    name = renamer()
    ballot_box = CompositeUniqueProperty('ballot_box')
    report = CompositeUniqueProperty('report', 'ballot')
    initiator = SharedUniqueProperty('initiator')
    subjects = SharedMultipleProperty('subjects')

    def __init__(self, ballot_type, electors, contexts, duration, **kwargs):
        super(Ballot, self).__init__(**kwargs)
        kwargs.pop('subjects', None)
        self.setproperty('ballot_box', BallotBox())
        self.setproperty('report',
                         Report(ballot_type, electors, contexts, **kwargs))
        self.run_at = None
        self.duration = duration
        self.finished_at = None
        self.period_validity = kwargs.get('period_validity', None)
        self.group = kwargs.get('group', DEFAULT_BALLOT_GROUP)
        self.uid = uuid.uuid4().hex
        self.__name__ = self.uid

    @property
    def group_id(self):
        group = getattr(self, 'group', DEFAULT_BALLOT_GROUP)
        return group.get('group_id', None)

    @property
    def is_finished(self):
        if 'finished' in self.state:
            return True

        now = datetime.datetime.now(tz=pytz.UTC)
        if now > self.finished_at:
            self.state.append('finished')
            return True

        return False

    @property
    def decision_is_valide(self):
        if 'expired' in self.state:
            return False

        if self.period_validity is None:
            return True

        now = datetime.datetime.now(tz=pytz.UTC)
        end_decision = self.finished_at + self.period_validity
        if now > end_decision:
            self.state.append('expired')
            return False

        return True

    def get_url(self, request):
        ballot_oid = get_oid(self, '')
        return request.resource_url(
            request.root, '@@seeballot', query={'id': ballot_oid}) \
            if ballot_oid else None

    def finish_ballot(self):
        if 'finished' not in self.state:
            self.finished_at = datetime.datetime.now(tz=pytz.UTC)
            self.state = PersistentList(['finished'])

    def run_ballot(self, context=None):
        """Run the ballot"""
        self.run_at = datetime.datetime.now(tz=pytz.UTC)
        self.finished_at = self.run_at + self.duration
        return self.report.ballottype.run_ballot(context)
Ejemplo n.º 29
0
class NovaIdeoApplication(CorrelableEntity, Debatable, Application):
    """Nova-Ideo class (Root)"""

    name = renamer()
    preregistrations = CompositeMultipleProperty('preregistrations')
    challenges = CompositeMultipleProperty('challenges')
    working_groups = CompositeMultipleProperty('working_groups')
    proposals = CompositeMultipleProperty('proposals')
    organizations = CompositeMultipleProperty('organizations')
    invitations = CompositeMultipleProperty('invitations')
    ideas = CompositeMultipleProperty('ideas')
    questions = CompositeMultipleProperty('questions')
    correlations = CompositeMultipleProperty('correlations')
    files = CompositeMultipleProperty('files')
    alerts = CompositeMultipleProperty('alerts')
    picture = CompositeUniqueProperty('picture')
    homepage_picture = CompositeUniqueProperty('homepage_picture')
    favicon = CompositeUniqueProperty('favicon')
    theme = CompositeUniqueProperty('theme')
    proposal_template = CompositeUniqueProperty('proposal_template')
    advertisings = CompositeMultipleProperty('advertisings')
    news_letter_members = SharedMultipleProperty('news_letter_members')
    general_chanel = SharedUniqueProperty('general_chanel')
    newsletters = CompositeMultipleProperty('newsletters')
    smart_folders = CompositeMultipleProperty('smart_folders')
    connectors = CompositeMultipleProperty('connectors')
    masks = CompositeMultipleProperty('masks')

    def __init__(self, **kwargs):
        super(NovaIdeoApplication, self).__init__(**kwargs)
        self.keywords = PersistentList()
        self.initialization()

    def __setattr__(self, name, value):
        super(NovaIdeoApplication, self).__setattr__(name, value)
        if name == 'mail_templates' and value:
            result = {}
            for template in value:
                mail_id = template.get('mail_id')
                languages = template.get('languages', [])
                languages = {m['locale']: m for m in languages}
                result[mail_id] = {
                    'title': template.get('title'),
                    'languages': languages
                }

            self._mail_templates = PersistentDict(result)

    @property
    def mail_conf(self):
        return self.get_data(
            omit(MailTemplatesConfigurationSchema(), '_csrf_token_'))

    @property
    def work_conf(self):
        result = self.get_data(
            omit(WorkParamsConfigurationSchema(), '_csrf_token_'))
        return result

    @property
    def user_conf(self):
        return self.get_data(
            omit(UserParamsConfigurationSchema(), '_csrf_token_'))

    @property
    def keywords_conf(self):
        return self.get_data(omit(KeywordsConfSchema(), '_csrf_token_'))

    @property
    def ui_conf(self):
        return self.get_data(
            omit(UserInterfaceConfigurationSchema(), '_csrf_token_'))

    @property
    def homepage_conf(self):
        return self.get_data(
            omit(HomepageConfigurationSchema(), '_csrf_token_'))

    @property
    def other_conf(self):
        return self.get_data(omit(OtherSchema(), '_csrf_token_'))

    @property
    def notif_conf(self):
        return self.get_data(
            omit(NotificationConfigurationSchema(), '_csrf_token_'))

    def get_newsletters_for_registration(self):
        return [
            nl for nl in self.newsletters
            if getattr(nl, 'propose_to_registration', True)
        ]

    def get_newsletters_automatic_registration(self):
        """Get newsletters with automatic registration"""
        return [
            nl for nl in self.newsletters
            if getattr(nl, 'automatic_registration', True)
        ]

    def initialization(self):
        self.reset_default_values()
        self.deadlines = PersistentList([datetime.datetime.now(tz=pytz.UTC)])
        self.work_modes = list(WORK_MODES.keys())
        self.colors_mapping = PersistentDict(DEFAULT_COLORS)

    def init_channels(self):
        if not self.general_chanel:
            self.addtoproperty('channels', Channel(title=_("General")))
            self.setproperty('general_chanel', self.channels[0])

    def reset_default_values(self):
        self.participants_mini = 3
        self.participants_maxi = 12
        self.participations_maxi = 5
        self.tokens_mini = 7

    @property
    def moderate_proposals(self):
        return 'proposal' in getattr(self, 'content_to_moderate', [])

    @property
    def moderate_ideas(self):
        return 'idea' in getattr(self, 'content_to_moderate', [])

    @property
    def examine_proposals(self):
        return 'proposal' in getattr(self, 'content_to_examine', [])

    @property
    def examine_ideas(self):
        return 'idea' in getattr(self, 'content_to_examine', [])

    @property
    def support_proposals(self):
        return 'proposal' in getattr(self, 'content_to_support', [])

    @property
    def support_ideas(self):
        return 'idea' in getattr(self, 'content_to_support', [])

    @property
    def manage_challenges(self):
        return 'challenge' in getattr(self, 'content_to_manage',
                                      DEFAULT_CONTENT_TO_MANAGE)

    @property
    def manage_questions(self):
        return 'question' in getattr(self, 'content_to_manage',
                                     DEFAULT_CONTENT_TO_MANAGE)

    @property
    def manage_proposals(self):
        return 'proposal' in getattr(self, 'content_to_manage',
                                     DEFAULT_CONTENT_TO_MANAGE)

    @property
    def titles(self):
        return DEFAULT_TITLES

    @property
    def comment_intentions(self):
        return DEFAULT_COMMENT_INTENTIONS

    @property
    def correlation_intentions(self):
        return DEFAULT_CORRELATION_INTENTIONS

    @property
    def idea_intentions(self):
        return DEFAULT_IDEA_INTENTIONS

    @property
    def amendment_intentions(self):
        return DEFAULT_AMENDMENT_INTENTIONS

    @property
    def channel(self):
        return getattr(self, 'general_chanel', None)

    def get_nonproductive_cycle_nb(self):
        return getattr(self, 'nonproductive_cycle_nb', 2)

    def init_files(self):
        for information in DEFAULT_FILES:
            if not self.get(information['name'], None):
                info_file = FileEntity(title=information['title'])
                content = information.get('content', '')
                content_file = information.get('content_file', None)
                if content_file:
                    content_path = os.path.join(os.path.dirname(__file__),
                                                'static', 'default_files',
                                                content_file)
                    if os.path.exists(content_path):
                        content = open(content_path).read()

                info_file.text = content
                info_file.__name__ = information['name']
                self.addtoproperty('files', info_file)
                info_file.state = PersistentList(['draft'])
                setattr(self, information['name'], info_file)

    def get_mail_template(self, id, locale=None):
        if locale is None:
            locale = self.locale

        mail = getattr(self, '_mail_templates', {}).get(id, None)
        if not mail:
            mail = DEFAULT_SITE_MAILS.get(id, None)

        template = mail.get('languages').get(locale, None)
        if not template:
            template = mail.get('languages').get(self.locale, None)

        return template

    def get_mail(self, id):
        for mail in getattr(self, 'mail_templates', {}):
            if mail.get('mail_id', None) == id:
                return mail

        template = DEFAULT_SITE_MAILS.get(id, None)
        if template:
            template = template.copy()
            template['mail_id'] = id
            template['languages'] = list(template['languages'].values())

        return template

    def get_site_sender(self):
        registry = get_current_registry()
        default_sender = registry.settings['mail.default_sender']
        return default_sender

    def get_work_modes(self):
        modes = getattr(self, 'work_modes', [])
        modes = {m: WORK_MODES[m] for m in modes if m in WORK_MODES}
        if modes:
            return modes

        return WORK_MODES

    def get_default_work_mode(self):
        modes = list(self.get_work_modes().values())
        modes = sorted(modes, key=lambda e: e.order)
        return modes[0]

    def add_colors_mapping(self, keys):
        if not hasattr(self, 'colors_mapping'):
            self.colors_mapping = PersistentDict(DEFAULT_COLORS)

        new_keywords = [k for k in keys if k not in self.colors_mapping]
        colors = random_color(len(new_keywords))
        for index, keyword in enumerate(new_keywords):
            self.colors_mapping[keyword] = {'color': colors[index]}

    def get_color(self, key):
        if key in getattr(self, 'colors_mapping', {}):
            return self.colors_mapping[key]

        self.add_colors_mapping([key])
        return self.colors_mapping[key]

    def merge_keywords(self, newkeywords):
        current_keywords = list(self.keywords)
        current_keywords.extend(newkeywords)
        self.keywords = PersistentList(list(set(current_keywords)))

    def get_title(self, user=None):
        return getattr(self, 'title', '')

    def get_connectors(self, connector_id):
        return filter(lambda c: c.connector_id == connector_id,
                      self.connectors)
Ejemplo n.º 30
0
class Proposal(VersionableEntity,
               SearchableEntity,
               DuplicableEntity,
               CorrelableEntity,
               PresentableEntity,
               ExaminableEntity,
               Node,
               Emojiable,
               SignalableEntity,
               Debatable,
               Tokenable):
    """Proposal class"""

    type_title = _('Proposal')
    icon = 'icon novaideo-icon icon-proposal'
    templates = {'default': 'novaideo:views/templates/proposal_result.pt',
                 'small': 'novaideo:views/templates/small_proposal_result.pt',
                 'popover': 'novaideo:views/templates/proposal_popover.pt',
                 'bloc': 'novaideo:views/templates/proposal_bloc.pt'}
    template = 'novaideo:views/templates/proposal_list_element.pt'
    name = renamer()
    author = SharedUniqueProperty('author')
    organization = SharedUniqueProperty('organization')
    working_group = SharedUniqueProperty('working_group', 'proposal')
    amendments = CompositeMultipleProperty('amendments', 'proposal')
    corrections = CompositeMultipleProperty('corrections', 'proposal')
    attached_files = SharedMultipleProperty('attached_files')
    challenge = SharedUniqueProperty('challenge', 'proposals')
    opinions_base = OPINIONS

    def __init__(self, **kwargs):
        super(Proposal, self).__init__(**kwargs)
        self.set_data(kwargs)
        self._amendments_counter = 1
        self.addtoproperty('channels', Channel())

    @property
    def related_ideas(self):
        return [idea[0] for idea in self.get_related_contents(
            CorrelationType.solid, ['related_ideas'])]

    @property
    def related_contents(self):
        return [content[0] for content in self.all_related_contents]

    @property
    def is_published(self):
        return 'published' in self.state

    @property
    def authors(self):
        authors = self.working_group.members
        author = self.author
        if author not in authors:
            authors.append(author)

        return authors

    @property
    def workspace(self):
        working_group = self.working_group
        if working_group:
            return working_group.workspace

        if self.current_version is not self:
            return getattr(self.current_version, 'workspace', None)

        return None

    def __setattr__(self, name, value):
        super(Proposal, self).__setattr__(name, value)
        if name == 'author':
            self.init_organization()

    def init_organization(self):
        if not self.organization:
            organization = getattr(self.author, 'organization', None)
            if organization:
                self.setproperty('organization', organization)

    def init_published_at(self):
        setattr(self, 'published_at', datetime.datetime.now(tz=pytz.UTC))

    def init_examined_at(self):
        setattr(self, 'examined_at', datetime.datetime.now(tz=pytz.UTC))

    def is_managed(self, root):
        return root.manage_proposals

    def get_more_contents_criteria(self):
        "return specific query, filter values"
        return None, {
            'metadata_filter': {
                'content_types': ['proposal', 'idea'],
                'keywords': list(self.keywords)
            }
        }

    def get_attached_files_data(self):
        return get_files_data(self.attached_files)

    def set_related_ideas(self, relatedideas, user):
        current_related_ideas = self.related_ideas
        related_ideas_to_add = [i for i in relatedideas
                                if i not in current_related_ideas]
        related_ideas_to_del = [i for i in current_related_ideas
                                if i not in relatedideas and
                                i not in related_ideas_to_add]
        connect(self,
                related_ideas_to_add,
                {'comment': _('Add related ideas'),
                 'type': _('Edit the proposal')},
                user,
                ['related_proposals', 'related_ideas'],
                CorrelationType.solid,
                True)
        disconnect(self,
                   related_ideas_to_del,
                   'related_ideas',
                   CorrelationType.solid)

    def get_version(self, user, parent):
        old_version = self.version
        copy_of_proposal = copy(
            self, parent,
            omit=('len_selections', 'graph'),
            roles=True)
        if old_version:
            copy_of_proposal.setproperty('version', old_version)

        copy_of_proposal.init_graph()
        copy_of_proposal.state = PersistentList(['version', 'archived'])
        copy_of_proposal.setproperty('author', self.author)
        copy_of_proposal.setproperty('originalentity', self.originalentity)
        for amendment in self.amendments:
            copy_of_proposal.addtoproperty('amendments', amendment)

        for correction in self.corrections:
            copy_of_proposal.addtoproperty('corrections', correction)

        for file_ in self.attached_files:
            copy_of_proposal.addtoproperty('attached_files', file_)

        copy_of_proposal.set_related_ideas(
            self.related_ideas, user)
        copy_of_proposal.reindex()
        return copy_of_proposal

    def remove_tokens(self, force=False):
        evaluators = self.evaluators()
        for user in evaluators:
            user.remove_token(self)
            user.remove_reserved_token(self)
            if force:
                self.remove_token(user)

    def get_node_descriminator(self):
        return 'proposal'