Ejemplo n.º 1
0
class Card(TimeStampedBase, OrderedModel):
    deck = models.ForeignKey(to=Deck, on_delete=models.CASCADE)
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    image = ThumbnailerImageField(
        upload_to=UploadToAppModelDirectory(),
        blank=True,
        resize_source=dict(size=(400, 400)),
    )
    content = MarkdownField(blank=True)
    categories = models.ManyToManyField(verbose_name=_('categories'),
                                        to=Category,
                                        blank=True)
    public = models.BooleanField(default=True)
    notes = MarkdownField(verbose_name=_("notes"),
                          help_text=_("Staff notes."),
                          blank=True)
    order_with_respect_to = 'deck'

    class Meta(OrderedModel.Meta):
        default_related_name = 'cards'
        unique_together = ['deck', 'name']

    def __str__(self):
        return self.name
Ejemplo n.º 2
0
class Demon(AutoOwnedBase, TimeStampedBase):
    name = models.CharField(verbose_name=_("name"), max_length=255, blank=True)
    avatar = models.URLField(_('avatar'), max_length=1000, blank=True)
    tensions = MarkdownField(blank=True)
    fears = MarkdownField(blank=True)
    content = MarkdownField(blank=True)

    class Meta:
        verbose_name = _('Demon')
        verbose_name_plural = _('Demons')
        default_related_name = 'demon'

    def __str__(self):
        return self.name or f"{self.owner}'s demon"
Ejemplo n.º 3
0
class Event(TimeStampedBase):
    name = models.CharField(
        verbose_name=_('name'),
        max_length=255,
    )
    start = models.DateTimeField(verbose_name=_('start'),
                                 default=get_current_date)
    end = models.DateTimeField(verbose_name=_('end'), null=True, blank=True)
    location = models.CharField(verbose_name=_('location'),
                                max_length=255,
                                blank=True)
    image_url = models.URLField(verbose_name=_('image url'),
                                max_length=1000,
                                blank=True)
    video_url = models.URLField(verbose_name=_('video url'),
                                max_length=1000,
                                blank=True)
    description = models.TextField(verbose_name=_('short description'),
                                   blank=True)
    content = MarkdownField(verbose_name=_('content'), )
    category = models.ForeignKey(to=Category,
                                 on_delete=models.SET_NULL,
                                 blank=True,
                                 null=True)
    participants = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        blank=True,
    )

    class Meta:
        default_related_name = 'events'
        ordering = ['-start']

    def __str__(self):
        return self.name
Ejemplo n.º 4
0
class Routine(OwnedBase, TimeStampedBase, OrderedModel):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    scope = ScopeField()
    content = MarkdownField(
        verbose_name=_('content'),
        blank=True
    )

    habits = models.ManyToManyField(
        to=Habit, through='RoutineHabit')

    # Reverse: owner, reminders
    # TODO: Related reminders

    @property
    def duration(self):
        return self.habits.aggregate(duration=Sum('duration')).get('duration')

    order_with_respect_to = 'owner'

    class Meta(OrderedModel.Meta):
        default_related_name = 'routines'

    def __str__(self):
        return self.name
Ejemplo n.º 5
0
class Joke(TimeStampedBase):
    """A motivational quote."""

    name = models.CharField(verbose_name=_("name"),
                            max_length=255,
                            unique=True,
                            help_text=_("What is the quote about?"))
    content = MarkdownField(blank=True)
    provider = models.ForeignKey(verbose_name=_('provider'),
                                 to=settings.AUTH_USER_MODEL,
                                 on_delete=models.SET_NULL,
                                 blank=True,
                                 null=True)
    accepted = models.BooleanField(verbose_name=_('accepted'), default=False)

    objects = JokeQuerySet.as_manager()

    def __str__(self):
        return self.name

    @property
    def pending(self):
        return not self.accepted

    def accept(self, save=True):
        self.accepted = True
        if save:
            self.save()

    class Meta:
        default_related_name = 'jokes'
Ejemplo n.º 6
0
class News(TimeStampedBase):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    author = models.ForeignKey(to=settings.AUTH_USER_MODEL,
                               on_delete=models.SET_NULL,
                               blank=True,
                               null=True)
    date = models.DateTimeField(_('date'), default=get_current_date)
    image_url = models.URLField(_('image url'), max_length=1000, blank=True)
    video_url = models.URLField(_('video url'), max_length=1000, blank=True)
    description = models.TextField(_('short description'), blank=True)
    content = MarkdownField()
    category = models.ForeignKey(to=Category,
                                 on_delete=models.SET_NULL,
                                 blank=True,
                                 null=True)

    class Meta:
        default_related_name = 'news'
        ordering = ['-date']
        verbose_name_plural = _('news')

    def __str__(self):
        return self.name
Ejemplo n.º 7
0
class Journal(AutoUrlsMixin, AutoOwnedBase):
    """
    A django model representing a user's journal.
    """

    spellchecker = models.BooleanField(default=False)
    day_template = MarkdownField(
        default=render_to_string('journals/dayentries_template.md'))
    week_template = MarkdownField(
        default=render_to_string('journals/weekentries_template.md'))
    month_template = MarkdownField(
        default=render_to_string('journals/monthentries_template.md'))
    year_template = MarkdownField(
        default=render_to_string('journals/yearentries_template.md'))
    streak = models.PositiveSmallIntegerField(
        _('streak'),
        default=0,
    )
    streak_max = models.PositiveSmallIntegerField(
        _('best streak'),
        default=0,
    )

    objects = JournalQuerySet.as_manager()

    class Meta:
        verbose_name = _('Journal')
        verbose_name_plural = _('Journals')

    def __str__(self):
        return "{}'s journal".format(self.owner)

    @property
    def index_url(self):
        return JournalPage.objects.first().url

    def reset(self):
        self.spellchecker = False
        self.day_template = render_to_string('journals/dayentries_template.md')
        self.week_template = render_to_string(
            'journals/weekentries_template.md')
        self.month_template = render_to_string(
            'journals/monthentries_template.md')
        self.year_template = render_to_string(
            'journals/yearentries_template.md')
        self.save()
        return True
Ejemplo n.º 8
0
class Quote(TimeStampedBase):
    """A motivational quote."""

    name = models.CharField(verbose_name=_("name"),
                            max_length=255,
                            unique=True,
                            help_text=_("What is the quote about?"))
    content = MarkdownField(blank=True)
    author = models.CharField(verbose_name=_('author'),
                              max_length=255,
                              blank=True)
    categories = models.ManyToManyField(verbose_name=_('categories'),
                                        to=Category)
    provider = models.ForeignKey(verbose_name=_('provider'),
                                 to=settings.AUTH_USER_MODEL,
                                 on_delete=models.SET_NULL,
                                 blank=True,
                                 null=True)
    accepted = models.BooleanField(verbose_name=_('accepted'), default=False)
    used_as_daily = models.DateField(null=True, blank=True, unique=True)
    liked_by = models.ManyToManyField(
        to=settings.AUTH_USER_MODEL,
        related_name='liked_quotes',
        blank=True,
    )
    disliked_by = models.ManyToManyField(
        to=settings.AUTH_USER_MODEL,
        related_name='disliked_quotes',
        blank=True,
    )

    objects = QuoteQuerySet.as_manager()

    def __str__(self):
        return self.name

    @property
    def pending(self):
        return not self.accepted

    def accept(self, save=True):
        self.accepted = True
        if save:
            self.save()
        # Notify user
        if self.provider:
            self.provider.contact(
                subject=f'Your quote "{self.name}" has been accepted. EOM')

    def like(self, user):
        self.disliked_by.remove(user)
        self.liked_by.add(user)

    def dislike(self, user):
        self.liked_by.remove(user)
        self.disliked_by.add(user)

    class Meta:
        default_related_name = 'quotes'
Ejemplo n.º 9
0
class Role(TimeStampedBase):
    kind = models.CharField(max_length=25,
                            choices=KIND_TYPES,
                            default=STANDARD)
    circle = models.ForeignKey(
        'self',
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        limit_choices_to={'kind': CIRCLE},
    )
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    nickname = models.CharField(_('nickname'), max_length=255, blank=True)
    item = models.CharField(_('item'), max_length=255, blank=True)
    icon = ThumbnailerImageField(
        upload_to='roles/icons/',
        blank=True,
        resize_source=dict(size=(100, 100)),
    )
    purpose = MarkdownField(_('purpose'), )
    strategy = MarkdownField(_('strategy'), blank=True)
    domains = MarkdownField(_('domains'), blank=True)
    accountabilities = MarkdownField(_('accountabilities'), blank=True)
    policies = MarkdownField(_('policies'), blank=True)
    history = MarkdownField(_('history'), blank=True)
    notes = MarkdownField(_('notes'), blank=True)
    checklists = MarkdownField(_('checklists'), blank=True)
    metrics = MarkdownField(_('metrics'), blank=True)
    description = models.TextField(blank=True)

    objects = RoleQuerySet.as_manager()

    class Meta:
        default_related_name = 'roles'
        ordering = ['name']
        unique_together = ['circle', 'name']

    def __str__(self):
        return '{}{}'.format(
            self.name,
            ' ({})'.format(self.nickname) if self.nickname else '',
        )

    @property
    def display_name(self):
        name = self.nickname or self.name
        return '{}'.format(name)
Ejemplo n.º 10
0
class Deck(TimeStampedBase):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    image = ThumbnailerImageField(
        upload_to=UploadToAppModelDirectory(),
        blank=True,
        resize_source=dict(size=(400, 400)),
    )
    content = MarkdownField(blank=True)
    notes = MarkdownField(verbose_name=_("notes"),
                          help_text=_("Staff notes."),
                          blank=True)

    class Meta:
        default_related_name = 'decks'

    def __str__(self):
        return self.name
Ejemplo n.º 11
0
class Tutorial(TimeStampedBase):
    name = models.CharField(_('name'), max_length=255, unique=True)
    video_url = models.URLField(_('video url'), max_length=1000, blank=True)
    content = MarkdownField()

    class Meta:
        default_related_name = 'tutorials'
        ordering = ['name']

    def __str__(self):
        return self.name
Ejemplo n.º 12
0
class Adventure(TimeStampedBase):
    name = models.CharField(
        _('name'),
        max_length=255,
        unique=True
    )
    scope = ScopeField(
    )
    public = models.BooleanField(
        default=False
    )
    image = ThumbnailerImageField(
        upload_to=UploadToAppModelDirectory(),
        blank=True,
        resize_source=dict(size=(400, 400)),
    )
    image_url = models.URLField(
        _('image url'),
        max_length=1000,
        blank=True
    )
    content = MarkdownField(
        blank=True
    )
    tags = models.ManyToManyField(
        to=AdventureTag,
        blank=True,
    )
    level = models.PositiveSmallIntegerField(
        _('level'),
        default=0,
    )
    notes = models.TextField(
        verbose_name=_("notes"),
        help_text=_("Staff notes."),
        blank=True
    )
    adventurers = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='AdventureReview'
    )

    @property
    def rating(self):
        return self.adventure_reviews.aggregate(Avg('rating')).get('rating__avg') or 0

    objects = AdventureQuerySet.as_manager()

    class Meta:
        default_related_name = 'adventures'
        ordering = ['name']

    def __str__(self):
        return self.name
Ejemplo n.º 13
0
class Tension(OwnedBase, TimeStampedBase):
    name = models.CharField(
        verbose_name=_('name'),
        max_length=255,
    )
    content = MarkdownField(verbose_name=_('content'), blank=True)

    class Meta:
        default_related_name = 'tensions'

    def __str__(self):
        return self.name
Ejemplo n.º 14
0
class Circle(TimeStampedBase):
    name = models.CharField(_('name'), max_length=255, unique=True)
    purpose = MarkdownField(_('purpose'), )
    strategy = MarkdownField(_('strategy'), blank=True)
    domains = MarkdownField(_('domains'), blank=True)
    accountabilities = MarkdownField(_('accountabilities'), blank=True)
    policies = MarkdownField(_('policies'), blank=True)
    history = MarkdownField(_('history'), blank=True)
    notes = MarkdownField(_('notes'), blank=True)
    checklists = MarkdownField(_('checklists'), blank=True)
    metrics = MarkdownField(_('metrics'), blank=True)

    # TODO: Adding outcomes

    class Meta:
        default_related_name = 'circles'

    def __str__(self):
        return self.name
Ejemplo n.º 15
0
class AdventureReview(OwnedBase, TimeStampedBase):
    adventure = models.ForeignKey(to=Adventure, on_delete=models.CASCADE)
    rating = models.PositiveSmallIntegerField(
        _('rating'), validators=[MinValueValidator(1),
                                 MaxValueValidator(5)])
    content = MarkdownField(blank=True)
    image_url = models.URLField(_('image url'), max_length=1000, blank=True)

    class Meta:
        default_related_name = 'adventure_reviews'
        unique_together = ['owner', 'adventure']

    def __str__(self):
        return '{adventure}/{user}'.format(adventure=self.adventure,
                                           user=self.owner)
Ejemplo n.º 16
0
class Quest(OrderedModel):
    name = models.CharField(verbose_name=_('name'),
                            max_length=255,
                            unique=True)
    video_url = models.URLField(verbose_name=_('video url'),
                                max_length=1000,
                                blank=True)
    content = MarkdownField(verbose_name=_('content'))

    # Reverse: objectives

    class Meta(OrderedModel.Meta):
        default_related_name = 'quests'

    def __str__(self):
        return self.name
Ejemplo n.º 17
0
class BookReview(OwnedBase, TimeStampedBase):
    book = models.ForeignKey(
        to=Book,
        on_delete=models.CASCADE
    )
    rating = models.PositiveSmallIntegerField(
        _('rating'),
        validators=[MinValueValidator(1), MaxValueValidator(5)]
    )
    area_1 = models.PositiveSmallIntegerField(
        _('area 1'),
        validators=[MaxValueValidator(100)]
    )
    area_2 = models.PositiveSmallIntegerField(
        _('area 2'),
        validators=[MaxValueValidator(100)]
    )
    area_3 = models.PositiveSmallIntegerField(
        _('area 3'),
        validators=[MaxValueValidator(100)]
    )
    area_4 = models.PositiveSmallIntegerField(
        _('area 4'),
        validators=[MaxValueValidator(100)]
    )
    area_5 = models.PositiveSmallIntegerField(
        _('area 5'),
        validators=[MaxValueValidator(100)]
    )
    area_6 = models.PositiveSmallIntegerField(
        _('area 6'),
        validators=[MaxValueValidator(100)]
    )
    area_7 = models.PositiveSmallIntegerField(
        _('area 7'),
        validators=[MaxValueValidator(100)]
    )
    content = MarkdownField()

    class Meta:
        default_related_name = 'book_reviews'
        unique_together = ['owner', 'book']

    def __str__(self):
        return 'Book review'
Ejemplo n.º 18
0
class JournalEntry(OwnedBase, TaggableBase, TimeStampedBase):
    """
    A django model representing a user's journal entry.
    """
    scope = models.CharField(
        _('scope'),
        choices=Scope.get_choices(),
        default=Scope.DAY.value,
        max_length=5,
    )
    start = models.DateField(_('start'), )

    content = MarkdownField(_('content'), blank=True)

    keywords = models.CharField(
        max_length=500,
        help_text="What were the most important experiences/topics?")

    @property
    def end(self):
        return self.get_scope().end

    def get_scope(self):
        return get_scope_by_name(self.scope)(self.start)

    objects = JournalEntryQuerySet.as_manager()

    class Meta:
        verbose_name = _('Journal Entry')
        verbose_name_plural = _('Journal entries')
        unique_together = ['owner', 'scope', 'start']
        ordering = ['-start']
        get_latest_by = 'start'
        default_related_name = 'journal_entries'

    def __str__(self):
        return "{} {}".format(self.get_scope_display(), self.start)

    def save(self, *args, **kwargs):
        if self.pk is None:  # Creation.
            # Adapting start date to scope.
            scope = self.get_scope()
            self.start = scope.start
            # self.end = scope.end
        super().save(*args, **kwargs)
Ejemplo n.º 19
0
class QuestObjective(OrderedModel):
    quest = models.ForeignKey(to=Quest, on_delete=models.CASCADE)
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    content = MarkdownField(verbose_name=_('content'), blank=True)
    code = models.CharField(
        _('code'),
        max_length=255,
    )

    order_with_respect_to = 'quest'

    class Meta(OrderedModel.Meta):
        default_related_name = 'objectives'

    def __str__(self):
        return self.name
Ejemplo n.º 20
0
class Quest(OrderedModel):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    video_url = models.URLField(_('video url'), max_length=1000, blank=True)
    content = MarkdownField(verbose_name=_('content'))

    # Reverse: objectives

    # questers = models.ManyToManyField(
    #     settings.AUTH_USER_MODEL,
    #     through='UserQuestStatus'
    # )

    class Meta(OrderedModel.Meta):
        default_related_name = 'quests'

    def __str__(self):
        return self.name
Ejemplo n.º 21
0
class Chapter(TimeStampedBase):
    story = models.ForeignKey(
        to=Story,
        on_delete=models.CASCADE,
    )
    name = models.CharField(
        _('name'),
        max_length=255,
        blank=True
    )
    content = MarkdownField()

    class Meta:
        verbose_name = _('Chapter')
        verbose_name_plural = _('Chapters')
        default_related_name = 'chapters'
        ordering = ['-created']

    def __str__(self):
        return "{}".format(self.name)
Ejemplo n.º 22
0
class Habit(OwnedBase, TimeStampedBase, OrderedModel):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    scope = ScopeField()
    icon = models.CharField(
        _('icon'),
        max_length=6,
        blank=True,
    )
    duration = IntuitiveDurationField(
        _('duration'),
        default=timezone.timedelta(minutes=10),
    )
    content = MarkdownField(verbose_name=_('content'), blank=True)
    is_active = models.BooleanField(
        verbose_name=_('active'),
        default=True,
    )
    is_controlled = models.BooleanField(
        verbose_name=_('controlled'),
        default=False,
        help_text=_(
            'Designates whether this habit is controlled by the system.'),
    )
    streak = models.PositiveSmallIntegerField(
        _('streak'),
        default=0,
    )
    streak_max = models.PositiveSmallIntegerField(
        _('best streak'),
        default=0,
    )

    @property
    def is_tracked(self):
        return self.has_track()

    def track(self):
        """
        Create a track record for this habit if not already present.
        And update the streak on successful track creation.
        :return:
            `track`: On tracking success
        """
        if not self.has_track():
            today = timezone.localtime(timezone.now()).date()
            # Create the new track record.
            track, created = self.track_events.get_or_create(
                created__date=today)
            if created:
                self.increase_streak()
                return track

    def has_track(self, date=None):
        """
        Check if a track record already exists (for the given date or today).
        :param date: The date to check for: If a track exists?
        :return: True if a track event was found. False if not found.
        """
        if date is None:
            date = timezone.localtime(timezone.now()).date()
        scope = get_scope_by_name(self.scope)(date)
        return self.track_events.filter(
            created__date__range=(scope.start, scope.end)).exists()

    def reset_streak(self, to=0):
        """
        Reset the streak and update the maximum streak if the new one is higher.
        :param to:
        :return:
        """
        updated_fields = ['streak']
        if self.streak > self.streak_max:
            self.streak_max = self.streak
            updated_fields += ['streak_max']
        self.streak = to
        self.save(update_fields=updated_fields)

    def increase_streak(self):
        self.streak += 1
        # Update max streak
        if self.streak > self.streak_max:
            self.streak_max = self.streak

    def get_stats(self, phases=4):
        """
        Check the last X phases for completion.

        Example:
            Performance of last 4 weeks?
            Result: [0, 1, 1, 0]
            => Not yet a success this week, success the 2 weeks before, no success 3 weeks ago.

        Result type: [{this_phase}, {last_phase}, {pre_last_phase}, {pre_pre_last_phase}]
        """
        # TODO: Refactor to static variables plus updates. (signals?).

        scope = get_scope_by_name(self.scope)()
        stats = [0 for x in range(phases)]  # [0, 0, 0, ...] empty result array

        for phase in range(phases):  # for each phase
            start = scope.start
            end = scope.end
            stats[phase] = self.track_events.filter(
                created__date__range=(start, end)).count()
            scope = scope.previous

        return stats

    # Reverse: owner, reminders, track_events

    order_with_respect_to = 'owner'

    objects = HabitQuerySet.as_manager()

    class Meta(OrderedModel.Meta):
        default_related_name = 'habits'

    def __str__(self):
        return self.name
Ejemplo n.º 23
0
class User(AbstractUser):
    """
    A django model representing a coLegend user/member called 'Legend'.
    """
    # First Name and Last Name do not cover name patterns
    # around the globe.
    name = models.CharField(
        verbose_name=_("name"),
        max_length=255,
        help_text=_("Your full name"),
    )
    # personal and contact data
    MALE = 'M'
    FEMALE = 'F'
    NEUTRAL = 'N'
    GENDER_CHOICES = (
        (MALE, _('male')),
        (FEMALE, _('female')),
        (NEUTRAL, _('neutral')),
    )
    gender = models.CharField(verbose_name=_('gender'),
                              max_length=1,
                              choices=GENDER_CHOICES,
                              default=NEUTRAL)

    birthday = models.DateField(
        verbose_name=_('birthday'),
        null=True,
        blank=True,
    )

    address = models.TextField(verbose_name=_('address'), blank=True)

    @property
    def city(self):
        address = self.address
        city = ''
        if address:
            parts = address.splitlines()
            if len(parts) >= 2:
                city = parts[1]
        return city

    phone = PhoneNumberField(
        verbose_name=_('phone'),
        blank=True,
        help_text=_('International format: e.g "+4917612345678"'))

    occupation = models.CharField(verbose_name=_('occupation(s)'),
                                  max_length=255,
                                  blank=True)

    avatar = ThumbnailerImageField(verbose_name=_('avatar'),
                                   upload_to=UploadToOwnedDirectory('avatars'),
                                   resize_source=dict(size=(400, 400)),
                                   blank=True)

    title = models.CharField(verbose_name=_('title'),
                             max_length=255,
                             blank=True)

    purpose = models.CharField(
        verbose_name=_("legend purpose"),
        max_length=255,
        help_text=
        _("I am a legend, <what you are doing or being> as <the role you are doing it as>."
          ),
        default=_(
            "I am a legend, defining my legend purpose as a member of coLegend."
        ))

    notes = MarkdownField(verbose_name=_("notes"),
                          help_text=_("Staff notes."),
                          blank=True)

    def add_note(self, note):
        if note:
            self.notes += '[{timestamp}] {note}\n'.format(
                timestamp=timezone.localtime(timezone.now()).isoformat(),
                note=note)
            self.save()

    def get_avatar(self, size=ImageSize.MEDIUM.value):
        # Issue with thumbnail creation:
        #  https://github.com/SmileyChris/easy-thumbnails/issues/499
        #  https://github.com/SmileyChris/easy-thumbnails/issues/503

        try:
            return self.avatar[size]
        except InvalidImageFormatError:
            if self.avatar:
                return self.avatar
        return self.avatar or self.get_avatar_fallback(size)

    def get_avatar_fallback(self, size=ImageSize.MEDIUM.value):
        email_md5 = hashlib.md5(
            self.email.encode('utf-8')).hexdigest() if self.email else ''
        name = quote_plus(self.name) if self.name else 'Anonymous'
        return 'https://www.gravatar.com/avatar/{email_md5}?s={size}&d=https%3A%2F%2Fui-avatars.com%2Fapi%2F/{name}/{size}/{bg_color}/{fg_color}'.format(
            email_md5=email_md5,
            name=name,
            size=settings.THUMBNAIL_ALIASES.get('')[size]['size'][0],
            bg_color='A5D6A7',
            fg_color='fff',
        )

    roles = models.ManyToManyField(
        Role,
        blank=True,
    )

    checkpoints = models.ManyToManyField(
        Checkpoint,
        through=UserCheckpoint,
        blank=True,
    )

    balance = models.SmallIntegerField(verbose_name=_('balance'),
                                       default=0,
                                       help_text=_('¤'))

    is_premium = models.BooleanField(
        verbose_name=_('premium'),
        default=False,
        help_text=_(
            'Designates whether this user has access to premium content.'),
    )

    status = models.TextField(
        verbose_name=_("status"),
        blank=True,
    )

    chat_id = models.CharField(
        verbose_name=_("chat id"),
        max_length=255,
        null=True,
        blank=True,
        unique=True,
    )

    duo = models.ForeignKey(verbose_name=_('duo'),
                            to=Duo,
                            related_name='members',
                            null=True,
                            blank=True,
                            on_delete=models.SET_NULL)

    clan = models.ForeignKey(verbose_name=_('clan'),
                             to=Clan,
                             related_name='members',
                             null=True,
                             blank=True,
                             on_delete=models.SET_NULL)

    tribe = models.ForeignKey(verbose_name=_('tribe'),
                              to=Tribe,
                              related_name='members',
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL)

    mentor = models.ForeignKey(verbose_name=_('mentor'),
                               to='self',
                               related_name='mentees',
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL)

    def has_checkpoint(self, name):
        return self.checkpoints.contains_name(name)

    def add_checkpoint(self, name):
        # Get the checkpoint.
        checkpoint, created = Checkpoint.objects.get_or_create(name=name)
        # Own it if not owned already.
        UserCheckpoint.objects.get_or_create(owner=self, checkpoint=checkpoint)
        return checkpoint

    def has_role(self, name):
        return self.is_superuser or self.roles.contains_name(name)

    def add_role(self, name):
        role, created = Role.objects.get_or_create(name=name)
        self.roles.add(role)
        return role

    @property
    def legend_days(self):
        date_joined = self.date_joined
        now = timezone.now()
        days = (now - date_joined).days
        return days

    @property
    def steps(self):
        steps = Step.objects.filter(outcome__owner=self)
        return steps

    def __str__(self):
        return self.username

    def get_absolute_url(self):
        return reverse('legends:detail', kwargs={'username': self.username})

    objects = UserManager()

    class Meta:
        verbose_name = 'legend'
        verbose_name_plural = 'legends'
        default_related_name = 'users'
        ordering = ['username']

    registration_country = models.CharField(max_length=255, blank=True)

    def get_pronoun(self, kind='subject'):
        gender = self.gender or self.NEUTRAL

        SUBJECT = 'subject'
        OBJECT = 'object'
        POSSESSIVE_ADJECTIVE = 'possessive adjective'
        POSSESSIVE_PRONOUN = 'possessive pronoun'
        REFLEXIVE_PRONOUN = 'reflexive pronoun'

        gender_pronouns = {
            self.MALE: {
                SUBJECT: 'he',
                OBJECT: 'him',
                POSSESSIVE_ADJECTIVE: 'his',
                POSSESSIVE_PRONOUN: 'his',
                REFLEXIVE_PRONOUN: 'himself',
            },
            self.FEMALE: {
                'subject': 'she',
                'object': 'her',
                'possessive adjective': 'her',
                'possessive pronoun': 'hers',
                'reflexive pronoun': 'herself',
            },
            self.NEUTRAL: {
                'subject': 'it',
                'object': 'it',
                'possessive adjective': 'its',
                'possessive pronoun': '',
                'reflexive pronoun': 'itself',
            },
        }
        return gender_pronouns.get(gender).get(kind)

    def contact(self, sender, subject=None, message=''):
        if not sender:
            sender = User.objects.get_or_create(username=SYSTEM_USER_USERNAME)
        if not subject:
            subject = 'Message from {name}'.format(name=sender)
        if self.email:
            email = EmailMessage(subject=subject,
                                 body=message,
                                 to=[self.email],
                                 reply_to=[sender.email])
            email.send()
Ejemplo n.º 24
0
class Book(TimeStampedBase):
    name = models.CharField(
        _('name'),
        max_length=255,
        unique=True
    )
    author = models.CharField(
        _('author'),
        max_length=255,
    )
    image_url = models.URLField(
        _('image url'),
        max_length=1000,
        blank=True
    )
    url = models.URLField(
        _('url'),
        max_length=1000,
        blank=True
    )
    content = MarkdownField(
        blank=True
    )
    public = models.BooleanField(
        default=False
    )
    featured = models.BooleanField(
        default=False
    )
    tags = models.ManyToManyField(
        to=BookTag,
        blank=True,
    )
    notes = models.TextField(
        verbose_name=_("notes"),
        help_text=_("Staff notes."),
        blank=True
    )

    rating = models.FloatField(
        _('rating'),
        default=0
    )

    def calculate_rating(self):
        rating = self.book_reviews.aggregate(Avg('rating')).get('rating__avg')
        return round(rating, 2) if rating else 0

    def update_rating(self):
        self.rating = self.calculate_rating()

    @property
    def area_ratings(self):
        return self.book_reviews.aggregate(
            area_1=Avg('area_1'),
            area_2=Avg('area_2'),
            area_3=Avg('area_3'),
            area_4=Avg('area_4'),
            area_5=Avg('area_5'),
            area_6=Avg('area_6'),
            area_7=Avg('area_7'),
        )

    objects = BookQuerySet.as_manager()

    class Meta:
        default_related_name = 'books'
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        # Making sure only one book can be featured.

        if self.featured:
            try:
                temp = Book.objects.get(featured=True)
                if self != temp:
                    temp.featured = False
                    temp.save()
            except Book.DoesNotExist:
                pass
        return super().save(*args, **kwargs)
Ejemplo n.º 25
0
class Habit(OwnedBase, TimeStampedBase, OrderedModel):
    name = models.CharField(
        _('name'),
        max_length=255,
    )
    scope = ScopeField()
    icon = models.CharField(
        _('icon'),
        max_length=6,
        blank=True,
    )
    duration = IntuitiveDurationField(
        _('duration'),
        default=timezone.timedelta(minutes=10),
    )
    content = MarkdownField(
        verbose_name=_('content'),
        blank=True
    )
    is_active = models.BooleanField(
        verbose_name=_('active'),
        default=True,
    )
    is_controlled = models.BooleanField(
        verbose_name=_('controlled'),
        default=False,
        help_text=_(
            'Designates whether this habit is controlled by the system.'
        ),
    )
    streak = models.PositiveSmallIntegerField(
        _('streak'),
        default=0,
    )
    streak_max = models.PositiveSmallIntegerField(
        _('best streak'),
        default=0,
    )

    def check_streak(self, date=None):
        if date is None:
            date = timezone.localtime(timezone.now()).date()
            scope = get_scope_by_name(self.scope)(date)
        else:
            scope = get_scope_by_name(self.scope)()
        return self.track_events.filter(created__date__range=(scope.start, scope.end)).exists()

    def reset_streak(self, to=0):
        updated_fields = ['streak']
        if self.streak > self.streak_max:
            self.streak_max = self.streak
            updated_fields += ['streak_max']
        self.streak = to
        self.save(update_fields=updated_fields)

    def get_stats(self, phases=4):
        """
        Check the last X phases for completion.

        Example:
            Performance of last 4 weeks?
            Result: [0, 1, 1, 0]
            => Not yet a success this week, success the 2 weeks before, no success 3 weeks ago.

        Result type: [{this_phase}, {last_phase}, {pre_last_phase}, {pre_pre_last_phase}]
        """
        # TODO: Refactor to static variables plus updates. (signals?).

        scope = get_scope_by_name(self.scope)()
        stats = [0 for x in range(phases)]  # [0, 0, 0, ...] empty result array

        for phase in range(phases):  # for each phase
            start = scope.start
            end = scope.end
            stats[phase] = self.track_events.filter(created__date__range=(start, end)).count()
            scope = scope.previous

        return stats

    # Reverse: owner, reminders, track_events

    order_with_respect_to = 'owner'

    objects = HabitQuerySet.as_manager()

    class Meta(OrderedModel.Meta):
        default_related_name = 'habits'

    def __str__(self):
        return self.name
Ejemplo n.º 26
0
class Lead(TimeStampedBase):
    name = models.CharField(
        verbose_name=_('name'),
        max_length=255,
    )
    status = models.ForeignKey(
        to=Status,
        on_delete=models.PROTECT,
        default=get_default_status
    )
    email = models.EmailField(
        _('email address'),
        blank=True,
        null=True,
        unique=True,
    )
    phone = PhoneNumberField(
        verbose_name=_('phone'),
        blank=True,
        help_text=_('International format: e.g "+4917612345678"')
    )
    url = models.URLField(
        _('url'),
        max_length=1000,
        blank=True,
        null=True,
        unique=True,
    )
    country = CountryField(
        verbose_name=_('country'),
        blank=True
    )
    address = models.TextField(
        verbose_name=_('address'),
        blank=True
    )
    gender = models.CharField(
        verbose_name=_('gender'),
        max_length=1,
        choices=User.GENDER_CHOICES,
        default=User.NEUTRAL
    )
    birthday = models.DateField(
        verbose_name=_('birthday'),
        null=True, blank=True,
    )
    history = MarkdownField(
        verbose_name=_('history'),
        blank=True
    )
    notes = MarkdownField(
        verbose_name=_('notes'),
        blank=True
    )
    tags = models.ManyToManyField(
        to=Tag,
        blank=True
    )
    first_contact = models.DateField(
        _('first contact'),
        blank=True,
        null=True,
        help_text=_('When was this lead first contacted?'),
    )
    last_contact = models.DateField(
        _('last contact'),
        blank=True,
        null=True,
        help_text=_('When was this lead last contacted?'),
    )
    next_contact = models.DateField(
        _('next contact'),
        blank=True,
        null=True,
        help_text=_('When will this lead be contacted next?'),
    )
    creator = models.ForeignKey(
        to=settings.AUTH_USER_MODEL,
        null=True, blank=True,
        on_delete=models.SET_NULL
    )

    @property
    def contact(self):
        return self.email or self.url or self.phone

    class Meta:
        default_related_name = 'leads'
        verbose_name = _("Lead")
        verbose_name_plural = _("Leads")
        ordering = ['created']

    def __str__(self):
        return self.name
Ejemplo n.º 27
0
class Vision(AutoUrlsMixin, OwnedBase, TimeStampedBase):
    """
    A django model representing a user's vision.
    """
    DAY = 1
    WEEK = 2
    MONTH = 3
    QUARTER = 4
    YEAR = 5
    SOMEDAY = 6
    SCOPE_CHOICES = (
        (DAY, _('day')),
        (WEEK, _('week')),
        (MONTH, _('month')),
        (QUARTER, _('quarter')),
        (YEAR, _('year')),
        (SOMEDAY, _('someday')),
    )
    SCOPE_MAP = OrderedDict(SCOPE_CHOICES)
    scope = models.PositiveSmallIntegerField(
        _('scope'),
        choices=SCOPE_CHOICES,
        default=DAY,
    )

    image = ThumbnailerImageField(verbose_name=_('image'),
                                  upload_to=UploadToOwnedDirectory('vision'),
                                  resize_source=dict(size=(1200, 1200)),
                                  blank=True)

    content = MarkdownField(blank=True)

    objects = VisionQuerySet.as_manager()

    class Meta:
        verbose_name = _('vision')
        verbose_name_plural = _('visions')
        default_related_name = 'visions'
        unique_together = ('owner', 'scope')

    def __str__(self):
        return "{}'s {} vision".format(self.owner, self.get_scope_display())

    @property
    def create_url(self):
        url = '{}create'.format(self.auto_url_prefix)
        return reverse(url, kwargs={'scope': self.get_scope_display()})

    @property
    def detail_url(self):
        url = '{}detail'.format(self.auto_url_prefix)
        return reverse(url, kwargs={'scope': self.get_scope_display()})

    @property
    def update_url(self):
        url = '{}update'.format(self.auto_url_prefix)
        return reverse(url, kwargs={'scope': self.get_scope_display()})

    @property
    def delete_url(self):
        url = '{}delete'.format(self.auto_url_prefix)
        return reverse(url, kwargs={'scope': self.get_scope_display()})
Ejemplo n.º 28
0
class Hero(AutoOwnedBase, TimeStampedBase):
    name = models.CharField(verbose_name=_("name"), max_length=255, blank=True)
    avatar = models.URLField(_('avatar'), max_length=1000, blank=True)
    year_topic = models.CharField(verbose_name=_("year topic"),
                                  max_length=255,
                                  blank=True)
    vision = MarkdownField(blank=True)
    mission = MarkdownField(blank=True)
    values = MarkdownField(blank=True)
    powers = MarkdownField(blank=True)
    skills = MarkdownField(blank=True)
    habits = MarkdownField(blank=True)
    principles = MarkdownField(blank=True)
    wishes = MarkdownField(blank=True)
    goals = MarkdownField(blank=True)
    people = MarkdownField(blank=True)
    resources = MarkdownField(blank=True)
    achievements = MarkdownField(blank=True)
    questions = MarkdownField(blank=True)
    experiments = MarkdownField(blank=True)
    projects = MarkdownField(blank=True)
    bucket = MarkdownField(blank=True, help_text="bucket list")
    inspirations = MarkdownField(blank=True)
    roles = MarkdownField(blank=True)
    strategy = MarkdownField(blank=True)
    topics = MarkdownField(blank=True)
    routines = MarkdownField(blank=True)
    blueprint_day = MarkdownField(blank=True)
    blueprint_week = MarkdownField(blank=True)
    blueprint_month = MarkdownField(blank=True)
    content = MarkdownField(blank=True)

    class Meta:
        verbose_name = _('Hero')
        verbose_name_plural = _('Heroes')
        default_related_name = 'hero'

    def __str__(self):
        return self.name or f"{self.owner}'s hero"