Example #1
0
class SurveyTicket(Notification):
    origin = db.ReferenceField(User)
    survey_unit = db.ListField(db.ReferenceField(SurveyUnit))

    def add_comment(self, text, user):
        if 'comments' not in self.payload:
            self.payload['comments'] = []
        comment_doc = {
            'user': user,
            'text': text,
            'added': datetime.now(),
            'id': int(datetime.now().timestamp())
        }
        self.payload['comments'].append(comment_doc)
        return comment_doc['id']

    def resolve(self):
        self.flagged = False

    @property
    def resolved_payload(self):
        pld = self.payload
        comments = []
        for comment in self.payload.get('comments', []):
            comments.append({
                'user': comment['user'].repr,
                'text': comment['text'],
                'added': str(comment['added']),
                'id': str(comment['id']),
            })
        pld['comments'] = comments
        return pld

    @property
    def repr(self):

        doc = {
            'id': str(self),
            'acquired': str(self.acquired),
            'flagged': self.flagged,
            'root_survey': self.survey_unit[-1].resolved_root.tiny_repr,
            'survey_unit': [_.tiny_repr for _ in self.survey_unit],
            'origin': str(self.origin),
            'cur_is_orgn': current_user.id == self.origin.id,
            'targets': [_.repr for _ in self.destined],
            'payload': self.resolved_payload,
            'type': self.__class__.__name__,
        }
        return doc
Example #2
0
class SurveySharePromise(Future):
    """
    Adds the User Credential after they Sign Up.
    """

    future_email = db.StringField(required=True)
    future_survey = db.ReferenceField(Survey)

    def routine(self):
        if not self.active:
            raise MethodUnavailable()
        usr = User.objects.get(email = self.future_email)
        grp = set(self.future_survey.created_by)
        grp.add(usr)
        self.future_survey.created_by = list(grp)
        self.future_survey.save()
        self.executed = True
        self.save()
        return self.repr

    @property
    def repr(self):
        return {
            'id': str(self),
            'future_email': self.future_email,
            'future_survey': self.future_survey.tiny_repr,
            'active': self.active,
            'executed': self.executed,
            'expires': str(self.expires),
            'url': self.url,
        }
Example #3
0
class Notification(db.Document):
    destined = db.ListField(db.ReferenceField(User))
    acquired = db.DateTimeField(default=datetime.now)
    released = db.DateTimeField(default=datetime.max)
    payload = db.DictField()

    #: Enables Inheritance.
    meta = {'allow_inheritance': True}

    def __unicode__(self):
        return HashId.encode(self.id)

    @property
    def flagged(self):
        return datetime.now() < self.released

    @flagged.setter
    def flagged(self, value):
        if value is True:
            self.released = datetime.max
        else:
            #: Sets time two seconds behind, to eliminate ANY possibility of
            #  race conditions and prevents other bugs, in general.
            self.released = datetime.now() - timedelta(seconds=2)

    @queryset_manager
    def past(doc_cls, queryset):
        return queryset.order_by('-acquired')

    @staticmethod
    def unflagged_count():
        return Notification.past(released__gt=datetime.now()).count()
Example #4
0
class Response(db.Document):
    parent_survey = db.ReferenceField(Survey)

    metadata = db.DictField()
    responses = db.DictField()

    def __unicode__(self):
        return HashId.encode(self.id)

    def add(self, qid, qres):
        if qid in self.parent_survey.cols:
            self.responses[qid] = qres
            self.metadata['modified'] = datetime.datetime.now()
            self.save()
        else:
            raise TypeError("Question ID is invalid")

        if qid in self.parent_survey.notification_hooks:
            if qres in self.parent_survey.notification_hooks[qid]:
                survey_response_notify.send(self.parent_survey,
                                            response=self,
                                            qid=qid,
                                            qres=qres)

    @property
    def added(self):
        return self.metadata[
            'started'] if 'started' in self.metadata else datetime.datetime.min
Example #5
0
class SurveyResponseNotification(Notification):
    survey = db.ReferenceField(Survey, required=True)
    response = db.ReferenceField(Response, required=True)
    transmit = db.BooleanField(default=False)

    @property
    def resolved_payload(self):
        fields = self.survey.resolved_root.struct.get('fields', [])
        payload = []
        flat_payload = [_ for _ in self.payload]
        for field in fields:
            "Look for matching questions, resolve options"
            "Todo: Resolve Answers "
            if field.get('cid') in flat_payload:
                q_field = field.get('field_options', {}).get('options', [])
                try:
                    res = self.payload.get(field['cid'])[2:].split('###')
                    res_label = [q_field[int(_) - 1].get('label') for _ in res]
                except Exception:
                    res_label = [""]
                payload.append({
                    'cid': field.get('cid'),
                    'label': field.get('label'),
                    'response': self.payload.get(field['cid']),
                    'res_label': res_label,
                })
        return payload

    @property
    def repr(self):
        doc = {
            'id': str(self),
            'acquired': str(self.acquired),
            'flagged': self.flagged,
            'survey': self.survey.tiny_repr,
            'root': self.survey.resolved_root.tiny_repr,
            'response': str(self.response),
            'payload': self.resolved_payload,
            'pl': self.payload,
            'type': self.__class__.__name__,
        }
        return doc
Example #6
0
class Attachment(db.Document):
    added = db.DateTimeField(default=datetime.datetime.now)
    modified = db.DateTimeField()
    filename = db.StringField(required=True)
    owner = db.ReferenceField(User)
    hidden = db.BooleanField(default=False)

    meta = {'allow_inheritance': True, 'strict': False}

    def __unicode__(self):
        return HashId.encode(self.id)

    def save(self, **kwargs):
        self.modified = datetime.datetime.now()
        super(Attachment, self).save(**kwargs)

    @queryset_manager
    def files(doc_cls, queryset):
        return queryset.filter(hidden=False)
Example #7
0
class Connection(db.Document):
    user_id = db.ReferenceField(User)

    provider_id = db.StringField()
    display_name = db.StringField()
    full_name = db.StringField()
    secret = db.StringField()
    email = db.StringField()
    provider_user_id = db.StringField()
    profile_url = db.StringField()
    image_url = db.StringField()
    access_token = db.StringField()

    def __unicode__(self):
        return HashId.encode(self.id)

    @property
    def user(self):
        return User.objects(email=self.user_id.id).first()
Example #8
0
class User(db.Document, UserMixin):
    email = db.EmailField(unique=True, required=True)
    password = db.StringField(required=True)

    metadata = db.DictField()

    active = db.BooleanField(default=True)
    added = db.DateTimeField(default=datetime.datetime.now)
    confirmed_at = db.DateTimeField()

    roles = db.ListField(db.ReferenceField(Role), default=[])

    def __unicode__(self):
        return HashId.encode(self.id)

    @property
    def repr(self):
        doc = {
            'id': str(self),
            'email': self.email,
        }
        return doc
Example #9
0
class SurveyUnit(Survey):
    referenced = db.ReferenceField(Survey, required=True)
    unit_name = db.StringField()

    def __init__(self, **kwargs):
        super(SurveyUnit, self).__init__(**kwargs)
        if self.referenced:
            self.structure = self.referenced.structure
            self.metadata.update(self.referenced.metadata)

    @property
    def units(self):
        "SurveyUnits cannot have Units."
        return None

    @property
    def resolved_root(self):
        return self.referenced.resolved_root

    @property
    def repr(self):
        return {
            'id': str(self),
            'unit_name': self.unit_name,
            'name': self.metadata['name'],
            'is_gamified': self.gamified_enabled,
            'uri_simple': '/survey/s:{0}/simple'.format(str(self)),
            'uri_game': '/survey/s:{0}/gamified'.format(str(self)),
            'uri_edit': '/survey/s:{0}/edit'.format(str(self)),
            'uri_responses': '/survey/s:{0}/analysis'.format(str(self)),
            'is_paused': self.paused,
            'is_active': self.active,
            'has_response_cap': self.response_cap,
            'has_obtained_responses': self.obtained_responses,
            'has_expired': self.expires <= datetime.datetime.now(),
            'expires': str(self.expires),
            'created_on': str(self.added),
            'last_modified': str(self.modified),
        }

    @property
    def repr_sm(self):
        return {
            'id': str(self),
            'rootid': str(self.resolved_root),
            'meta': {
                'name': self.unit_name,
                'rootname': self.resolved_root.metadata['name'],
                'type': self._cls,
            },
            'status': {
                'paused': self.paused,
                'active': self.active,
                'response_cap': self.response_cap,
                'response_count': self.obtained_responses,
                'expired': self.expires <= datetime.datetime.now(),
                'unit_count': False,
            },
            'access': {
                'accessible': [_.repr for _ in self.created_by],
                'editable': False,  #: Unit Survey
                'owner': current_user() in self.resolved_root.created_by,
            },
            'info': {
                'expires': str(self.expires),
                'added': str(self.added),
                'modified': str(self.modified),
            }
        }

    @property
    def tiny_repr(self):
        return {
            'id': str(self),
            'name': self.unit_name,
            'active': self.active,
        }

    @queryset_manager
    def objects(doc_cls, queryset):
        return queryset.filter()
Example #10
0
class Survey(db.Document):
    added = db.DateTimeField(default=datetime.datetime.now)

    metadata = db.DictField()
    structure = db.DictField()
    attachments = db.ListField(db.ReferenceField(AttachmentImage))

    created_by = db.ListField(db.ReferenceField(User))

    meta = {'allow_inheritance': True, 'strict': False}

    def __unicode__(self):
        return HashId.encode(self.id)

    @property
    def resolved_root(self):
        return self

    @property
    def cols(self):
        return [_['cid'] for _ in self.structure['fields']]

    @property
    def notification_hooks(self):
        rules = {}
        for field in self.structure['fields']:
            if field.get('notifications', False) is True:
                options = enumerate(field['field_options'].get('options', []))
                store = []
                for i, option in options:
                    if option.get('notify', False) is True:
                        store.append("a_{0}".format(i + 1))
                rules[field['cid']] = store

        return rules

    @property
    def questions(self):
        return [[_['cid'], _['label']] for _ in self.structure['fields']]

    @property
    def expires(self):
        return self.metadata[
            'expires'] if 'expires' in self.metadata else datetime.datetime.max

    @expires.setter
    def expires(self, value):
        self.metadata['expires'] = value

    @property
    def active(self):
        time_now = datetime.datetime.now()
        return all([
            not self.hidden,
            time_now <= self.expires,
            not self.paused,
            self.response_cap > self.obtained_responses,
        ])

    @property
    def paused(self):
        return self.metadata['paused'] if 'paused' in self.metadata else False

    @paused.setter
    def paused(self, value):
        self.metadata['paused'] = value

    @property
    def response_cap(self):
        return self.metadata[
            'response_cap'] if 'response_cap' in self.metadata else 2**32

    @property
    def obtained_responses(self):
        return ResponseAggregation(self).count

    @response_cap.setter
    def response_cap(self, value):
        self.metadata['response_cap'] = value

    @property
    def struct(self):
        ret = {}
        ret['fields'] = self.structure.get('fields',
                                           starter_template['fields'])
        ret['screens'] = self.structure.get('screens',
                                            starter_template['screens'])
        ret['links'] = self.structure.get('links', None)

        return ret

    @struct.setter
    def struct(self, value):
        try:
            validate(value, survey_struct_schema)
            self.structure.update(value)
        except ValidationError as e:
            raise TypeError('Struct value invalid' + str(e))

    #: DEPRECATED
    @property
    def gamified_enabled(self):
        return False

    @property
    def modified(self):
        return self.metadata[
            'modified'] if 'modified' in self.metadata else self.added

    @property
    def img_uploads(self):
        return [_.repr for _ in self.attachments]

    @property
    def hidden(self):
        return self.metadata['hidden'] if 'hidden' in self.metadata else False

    @hidden.setter
    def hidden(self, value):
        self.metadata['hidden'] = value

    @property
    def units(self):
        dat = SurveyUnit.objects(referenced=self)
        return [_.repr for _ in dat if not _.hidden]

    @property
    def unit_count(self):
        return SurveyUnit.objects(referenced=self).count()

    @property
    def units_as_objects(self):
        dat = SurveyUnit.objects(referenced=self)
        return [_ for _ in dat if not _.hidden]

    def save(self, **kwargs):
        self.metadata['modified'] = datetime.datetime.now()
        super(Survey, self).save(**kwargs)

    @queryset_manager
    def objects(doc_cls, queryset):
        return queryset.filter()

    @queryset_manager
    def root(doc_cls, queryset):
        return queryset.filter(_cls='Survey')

    #: DEPRECATION WARNING: WILL BE CHANGED.
    @property
    def repr(self):
        return {
            'id': str(self),
            'name': self.metadata['name'],
            'is_gamified': self.gamified_enabled,
            'uri_simple': '/survey/s:{0}/simple'.format(str(self)),
            'uri_game': '/survey/s:{0}/gamified'.format(str(self)),
            'uri_edit': '/survey/s:{0}/edit'.format(str(self)),
            'uri_responses': '/survey/s:{0}/analysis'.format(str(self)),
            'is_paused': self.paused,
            'is_active': self.active,
            'imgs': self.img_uploads,
            'units': self.units,
            'has_response_cap': self.response_cap,
            'has_obtained_responses': self.obtained_responses,
            'has_expired': self.expires <= datetime.datetime.now(),
            'expires': str(self.expires),
            'created_on': str(self.added),
            'last_modified': str(self.modified),
        }

    @property
    def repr_sm(self):
        return {
            'id': str(self),
            'meta': {
                'name': self.metadata['name'],
                'type': self._cls,
            },
            'status': {
                'paused': self.paused,
                'active': self.active,
                'response_cap': self.response_cap,
                'response_count': self.obtained_responses,
                'expired': self.expires <= datetime.datetime.now(),
                'unit_count': self.unit_count,
            },
            'access': {
                'accessible': [_.repr for _ in self.created_by],
                'editable': True,  #: Root Survey
                'owner': True,
            },
            'info': {
                'expires': str(self.expires),
                'added': str(self.added),
                'modified': str(self.modified),
            }
        }

    @property
    def tiny_repr(self):
        return {
            'id': str(self),
            'name': self.metadata['name'],
            'active': self.active,
        }

    #: DEPRECATED
    @property
    def render_json(self):
        #: DEPRECATION WARNING: This method will be removed.
        rt = {}
        rt['fields'] = []
        rt['game_title'] = ""
        rt['game_description'] = ""
        rt['game_footer'] = ""
        rt['survey_logo'] = ""
        rt['WARNING'] = "This Feature has been deprecated.\
            It will be removed in coming versions.\
            This API Call has been preserved for backwards\
            compatibility."

        return rt

    @property
    def render_deepjson(self):

        rt = {}
        cp = self.struct['fields']

        def logic(id_next):
            return {'va': id_next}

        for i in range(len(cp)):
            option_len = len(cp[i]['field_options'].get('options', []))
            for j in range(option_len):
                img = cp[i]['field_options']['options'][j].get('img_uri', None)
                if img is not None:
                    cp[i]['field_options']['options'][j][
                        'img_uri'] = Uploads.url_for_surveyimg(img)
            cp[i]['next'] = logic('end' if (i +
                                            1) >= len(cp) else cp[i +
                                                                  1]['cid'])

        rt['fields'] = cp
        rt['survey_title'] = self.struct['screens'][0]

        give_img = len(self.struct['screens']) >= 4 and len(
            self.struct['screens'][3]) > 1

        rt['survey_logo'] = Uploads.url_for_surveyimg(
            self.struct['screens'][3]) if give_img else False
        rt['survey_description'] = self.struct['screens'][1]
        rt['survey_footer'] = self.struct['screens'][2]
        return rt