示例#1
0
文件: models.py 项目: NewRGB/lino
class Volume(Referrable):

    class Meta:
        app_label = 'uploads'
        verbose_name = _("Library volume")
        verbose_name_plural = _("Library volumes")

    preferred_foreignkey_width = 5

    root_dir = dd.CharField(_("Root directory"), max_length=255)
    base_url = dd.CharField(_("Base URL"), max_length=255, blank=True)
    description = dd.CharField(_("Description"), max_length=255, blank=True)

    def __str__(self):
        return self.ref or self.root_dir

    def get_filenames(self):
        root_len = len(self.root_dir) + 1
        for (root, dirs, files) in os.walk(self.root_dir):
            relroot = root[root_len:]
            if relroot:
                relroot += "/"
            for fn in files:
                # print(relroot + "/" + fn)
                yield relroot + fn
示例#2
0
class Matching(dd.Model):
    class Meta:
        abstract = True

    match = dd.CharField(
        _("Match"), max_length=20, blank=True,
        help_text=_("The movement to be matched."))

    @classmethod
    def get_match_choices(cls, journal, partner):
        """This is the general algorithm.
        """
        matchable_accounts = rt.models.ledger.Account.objects.filter(
            matchrule__journal=journal)
        fkw = dict(account__in=matchable_accounts)
        fkw.update(cleared=False)
        if partner:
            fkw.update(partner=partner)
        qs = rt.models.ledger.Movement.objects.filter(**fkw)
        qs = qs.order_by('value_date')
        # qs = qs.distinct('match')
        return qs.values_list('match', flat=True)

    @dd.chooser(simple_values=True)
    def match_choices(cls, journal, partner):
        # todo: move this to implementing classes?
        return cls.get_match_choices(journal, partner)

    def get_match(self):
        # return self.match or self.get_default_match()
        return self.match or self  # 20191226
示例#3
0
class SignIn(dd.Action):
    label = _("Sign in")
    select_rows = False
    parameters = dict(username=dd.CharField(_("Username")),
                      password=dd.PasswordField(_("Password"), blank=True))
    # params_layout = dd.ActionParamsLayout("""
    params_layout = dd.Panel("""
    username
    password
    """,
                             label_align=layouts.LABEL_ALIGN_LEFT)

    http_method = "POST"

    def run_from_ui(self, ar, **kw):
        pv = ar.action_param_values
        user = auth.authenticate(ar.request,
                                 username=pv.username,
                                 password=pv.password)
        if user is None:
            ar.error(_("Failed to log in as {}.".format(pv.username)))
        else:
            # user.is_authenticated:
            auth.login(ar.request, user)
            ar.success(_("Now logged in as {}").format(user),
                       close_window=True,
                       goto_url=ar.renderer.front_end.build_plain_url())
示例#4
0
文件: models.py 项目: forexblog/xl
class ContactDetail(dd.Model):
    class Meta:
        app_label = 'phones'
        verbose_name = _("Contact detail")
        verbose_name_plural = _("Contact details")

    detail_type = ContactDetailTypes.field(default='email')
    partner = dd.ForeignKey(
        dd.plugins.phones.partner_model,
        related_name='phones_by_partner')
    value = dd.CharField(_("Value"), max_length=200, blank=True)
    remark = dd.CharField(_("Remark"), max_length=200, blank=True)
    primary = models.BooleanField(_("Primary"), default=False)
    end_date = models.DateField(_("Until"), blank=True, null=True)

    allow_cascaded_delete = ['partner']

    def __str__(self):
        return self.detail_type.format(self.value)

    def full_clean(self):
        super(ContactDetail, self).full_clean()
        self.detail_type.validate(self.value)

    def after_ui_save(self, ar, cw):
        super(ContactDetail, self).after_ui_save(ar, cw)
        mi = self.partner
        if mi is None:
            return
        if self.primary and self.detail_type:
            for o in mi.phones_by_partner.exclude(id=self.id).filter(
                    detail_type=self.detail_type):
                if o.primary:
                    o.primary = False
                    o.save()
                    ar.set_response(refresh_all=True)
        k = self.detail_type.field_name
        if k:
            watcher = ChangeWatcher(mi)
            setattr(mi, k, self.value)
            watcher.send_update(ar)
            mi.save()

    @classmethod
    def get_simple_parameters(cls):
        return ['partner', 'detail_type']
示例#5
0
文件: models.py 项目: NewRGB/lino
class Change(dd.Model):
    """A registered change in the database.

    Each database change of a watched object will generate one Change
    record.

    .. attribute:: master

        The database object which acts as "master".
    
    .. attribute:: object

        The database object which has been modified.
    
    
    """
    class Meta(object):
        verbose_name = _("Change")
        verbose_name_plural = _("Changes")

    # allow_cascaded_delete = 'master'
    quick_search_fields = 'changed_fields diff'
    show_in_site_search = False

    time = models.DateTimeField()
    type = ChangeTypes.field()
    if settings.SITE.user_model:
        user = dd.ForeignKey(settings.SITE.user_model)
    else:
        user = dd.DummyField()

    object_type = dd.ForeignKey('contenttypes.ContentType',
                                blank=True,
                                null=True,
                                verbose_name=_("Object type"),
                                related_name='changes_by_object')
    object_id = GenericForeignKeyIdField(object_type, blank=True, null=True)
    object = GenericForeignKey('object_type', 'object_id', _("Object"))

    master_type = dd.ForeignKey('contenttypes.ContentType',
                                blank=True,
                                null=True,
                                verbose_name=_("Master type"),
                                related_name='changes_by_master')
    master_id = GenericForeignKeyIdField(master_type, blank=True, null=True)
    master = GenericForeignKey('master_type', 'master_id', _("Master"))

    diff = dd.RichTextField(_("Changes"),
                            format='plain',
                            blank=True,
                            editable=False)
    changed_fields = dd.CharField(_("Fields"), max_length=250, blank=True)

    def __str__(self):
        # ~ return "#%s - %s" % (self.id,self.time)
        return "#%s" % self.id
示例#6
0
class ChatGroup(UserAuthored, Created, Referrable):
    class Meta(object):
        app_label = 'chat'
        verbose_name = _("Chat group")
        verbose_name_plural = _("Chat groups")
        ordering = ['created', 'id']

    title = dd.CharField(max_length=20)
    description = dd.RichTextField(max_length=200, blank=True, null=True)
    ticket = dd.ForeignKey("tickets.Ticket", blank=True, null=True)

    @dd.action(_("getChatGroups"))
    def getChatGroups(self, ar):
        """
        Returns info on all GroupChats for this user.
        """
        qs = ChatGroupMember.objects.filter(
            user=ar.get_user()).select_related("group")

        rows = [{
            "id": cp.group.pk,
            "title": cp.group.title,
            "unseen": cp.group.get_unseen_count(ar)
        } for cp in qs]

        return ar.success(rows=rows)

    def get_unseen_count(self, ar):
        """
        Returns count of messages that haven't been seen yet."""
        return ChatProps.objects.filter(chat__group=self,
                                        user=ar.get_user(),
                                        seen__isnull=True).count()

    @dd.action(_("Load GroupChat"))
    def loadGroupChat(self, ar):
        """Returns chat messages for a given chat"""
        rows = []
        if 'mk' in ar.rqdata:
            # master = rt.models.resolve("contenttypes.ContentType").get(pk=ar.rqdata['mt']).get(pk=ar.rqdata["mk"])
            ar.selected_rows = [
                ChatGroup.objects.get(ticket__pk=ar.rqdata['mk'])
            ]
        for group in ar.selected_rows:
            last_ten = ChatProps.objects.filter(
                user=ar.get_user(),
                chat__group=group).order_by('-created').select_related("chat")
            rows.append({
                'title': group.title,
                'id': group.id,
                'messages': [cp.serialize(ar) for cp in last_ten]
            })
        return ar.success(rows=rows)
示例#7
0
文件: models.py 项目: DarioGT/lino
class Foo(dd.Model):

    name = models.CharField(max_length=100, blank=True)
    remarks = models.TextField("Remarks", blank=True)
    input_mask_test = dd.CharField(
        "Question text",
        blank=True,
        max_length=200,
        help_text="""This field is here to play with the
        CharField parameters regex, mask_re and strip_chars_re.
        By default it accepts all letters except Z.
        """,
        #~ regex='/^[a-yA-Y]*$/')
        mask_re='/^[a-yA-Y]*$/')
示例#8
0
class Matching(dd.Model):
    """Model mixin for database objects that are considered *matching
    transactions*.  A **matching transaction** is a transaction that
    points to some other movement which it "clears" at least partially.

    A movement is cleared when its amount equals the sum of all
    matching movements.

    Adds a field :attr:`match` and a chooser for it.  Requires a field
    `partner`.  The default implementation of the chooser for
    :attr:`match` requires a `journal`.

    Base class for :class:`lino_cosi.lib.vat.AccountInvoice`
    (and e.g. `lino_cosi.lib.sales.Invoice`, `lino_cosi.lib.finan.DocItem`)
    
    .. attribute:: match

       Pointer to the :class:`movement
       <lino.modlib.ledger.models.Movement>` which is being cleared by
       this movement.

    """
    class Meta:
        abstract = True

    match = dd.CharField(_("Match"),
                         max_length=20,
                         blank=True,
                         help_text=_("The movement to be matched."))

    @classmethod
    def get_match_choices(cls, journal, partner):
        """This is the general algorithm.
        """
        matchable_accounts = rt.modules.accounts.Account.objects.filter(
            matchrule__journal=journal)
        fkw = dict(account__in=matchable_accounts)
        fkw.update(cleared=False)
        if partner:
            fkw.update(partner=partner)
        qs = rt.modules.ledger.Movement.objects.filter(**fkw)
        qs = qs.order_by('value_date')
        # qs = qs.distinct('match')
        return qs.values_list('match', flat=True)

    @dd.chooser(simple_values=True)
    def match_choices(cls, journal, partner):
        # todo: move this to implementing classes?
        return cls.get_match_choices(journal, partner)
示例#9
0
文件: models.py 项目: forexblog/xl
class GooglePeople(dd.Model):
    class Meta:
        abstract = True

    google_resourceName = dd.CharField(max_length=200, verbose_name=_('Google ResourceName'), blank=True)
    google_contactID = dd.CharField(max_length=200, verbose_name=_('Google Contact ID'), blank=True)

    def save(self, *args, **kw):
        if not self.google_resourceName and self.name:
            body = {'names': [{'displayName': self.name, "givenName": self.last_name, "familyName": self.first_name}]}
            if self.email:
                body['emailAddresses'] = [{'value': self.email, 'type': 'work'}]
            if dd.is_installed('phones'):
                body.update(
                    {'PhoneNumber': [{'value': self.phone, 'type': 'main'}, {'value': self.gsm, 'type': 'mobile'}]})
            try:
                results = service.people().createContact(body=body).execute()
                if results and results.get('resourceName', False):
                    self.google_resourceName = results.get('resourceName', False)
                    self.google_contactID = results.get('resourceName', False).split('/')[1]
            except HttpError as e:
                print(e.content)
        elif self.google_resourceName:
            try:
                contactToUpdate = service.people().get(resourceName=self.google_resourceName,
                                                       personFields='names,emailAddresses').execute()
                contactToUpdate['names'] = [
                    {'displayName': self.name, "givenName": self.last_name,
                     "familyName": self.first_name}]
                service.people().updateContact(resourceName=self.google_resourceName,
                                               updatePersonFields='names,emailAddresses',
                                               body=contactToUpdate).execute()
            except HttpError as e:
                print(e.content)
        res = super(GooglePeople, self).save(*args, **kw)
        return res
示例#10
0
文件: actions.py 项目: gary-ops/lino
class SignInWithSocialAuth(SignIn):
    # 20171207 nice as an example of a action dialog window with a
    # HtmlBox, but we don't currently use it.
    parameters = dict(
        social_auth_links=dd.HtmlBox(
            # _("Other authentications"),
            default=E.div(*settings.SITE.get_social_auth_links())),
        # social_auth_links=dd.Constant(
        #     settings.SITE.get_social_auth_links),
        # social=social_auth_field(),
        username=dd.CharField(_("Username")),
        password=dd.PasswordField(_("Password"), blank=True)
    )
    # params_layout = dd.ActionParamsLayout("""
    params_layout = dd.Panel("""
    username
    password
    social_auth_links
    """, label_align="left", window_size=(60,10))
示例#11
0
文件: models.py 项目: forexblog/xl
class Plan(Referrable):

    ref_max_length = 30

    class Meta:
        app_label = 'healthcare'
        abstract = dd.is_abstract_model(__name__, 'Plan')
        verbose_name = _("Healthcare plan")
        verbose_name_plural = _("Healthcare plans")

    provider = dd.ForeignKey('contacts.Company',
                             related_name="healthcare_plans_by_provider",
                             verbose_name=_("Provider"),
                             blank=True,
                             null=True)

    remark = dd.CharField(_("Remark"), max_length=200, blank=True)

    def __str__(self):
        if self.ref:
            return self.ref
        else:
            return str(self.provider)
示例#12
0
class Tag(dd.Model):

    name = dd.CharField(max_length=100)

    def __str__(self):
        return self.name
示例#13
0
文件: models.py 项目: forexblog/xl
class Meeting(Referrable, Milestone, Reservation, Duplicable, Starrable):
    """A Meetings is a list of tickets that are to be discussed with a group of people
    """
    # .. attribute:: max_places
    #
    #     Available places. The maximum number of participants to allow
    #     in this course.
    #
    # """
    workflow_state_field = 'state'

    class Meta:
        app_label = 'meetings'
        verbose_name = _("Meeting")
        verbose_name_plural = _('Meetings')
        # verbose_name = _("Event")
        # verbose_name_plural = _('Events')

    description = dd.RichTextField(_("Description"), blank=True)

    child_starrables = [('deploy.Deployment', 'milestone', 'ticket')]

    quick_search_fields = 'name description ref'
    site_field_name = 'site'

    site = dd.ForeignKey('tickets.Site', blank=True, null=True)

    state = MeetingStates.field(default=MeetingStates.as_callable('draft'))

    name = dd.CharField(_("Title"), max_length=100, blank=True)

    def on_duplicate(self, ar, master):
        # self.state = CourseStates.draft
        # def OK(ar):
        self.state = MeetingStates.draft
        # ar.confirm(OK,_("Remove inactive tickets on new meeting?"))
        old = ar.selected_rows[0]
        if self.ref:
            old.ref = datetime.now().strftime("%Y%m%d") + "@" + old.ref
            old.full_clean()
            old.save()
        super(Referrable, self).on_duplicate(ar, master)

    def after_duplicate(self, ar, master):
        rt.models.deploy.Deployment.objects.filter(
            Q(milestone=self),
            Q(new_ticket_state__in=TicketStates.filter(active=False))
            | Q(ticket__state__in=TicketStates.filter(active=False))).delete()
        rt.models.deploy.Deployment.objects.filter(milestone=self).update(
            new_ticket_state=None,
            old_ticket_state=None,
            remark="",
        )
        stars = rt.models.stars.Star.for_obj(
            master, )  #no master__isnull since we want to copy the site star
        for s in stars:
            s.owner = self
            s.id = None
            s.save()

    def __str__(self):
        if self.ref:
            return self.ref
        if self.name:
            return self.name
        if self.room is None:
            return "(%s)" % (dd.fds(self.start_date))
        # Note that we cannot use super() with
        # python_2_unicode_compatible
        return "(%s@%s)" % (dd.fds(self.start_date), self.room)

    def update_cal_from(self, ar):
        """Note: if recurrency is weekly or per_weekday, actual start may be
        later than self.start_date

        """
        return self.start_date

    def update_cal_event_type(self):
        return None

    def full_clean(self, *args, **kw):
        super(Meeting, self).full_clean(*args, **kw)

    def get_milestone_users(self):
        #todo
        if dd.is_installed("stars"):
            for s in rt.models.stars.Star.for_obj(self):
                # u = obj.partner.get_as_user()
                # if u is not None:
                yield s.user

    def site_changed(self, ar):
        """Leaves a sub-star of old site, but that's OK for now"""
        if self.site is not None:
            self.site.add_child_stars(self.site, self)
            # self.add_change_watcher(star.user)

    def after_ui_create(self, ar):
        self.site_changed(ar)
        super(Meeting, self).after_ui_create(ar)

    @classmethod
    def add_param_filter(cls,
                         qs,
                         lookup_prefix='',
                         show_active=None,
                         **kwargs):
        qs = super(Meeting, cls).add_param_filter(qs, **kwargs)
        active_states = MeetingStates.filter(active=True)
        fkw = dict()
        fkw[lookup_prefix + 'state__in'] = active_states
        if show_active == dd.YesNo.no:
            qs = qs.exclude(**fkw)
        elif show_active == dd.YesNo.yes:
            qs = qs.filter(**fkw)
        return qs

    @classmethod
    def quick_search_filter(model, search_text, prefix=''):
        q = Q()
        if search_text.isdigit():
            for fn in model.quick_search_fields:
                kw = {prefix + fn.name + "__icontains": search_text}
                q = q | Q(**kw)
            return q
        #Skip referable's method
        return super(Referrable,
                     model).quick_search_filter(search_text, prefix)
示例#14
0
class Page(Hierarchical, Sequenced, Previewable, Publishable):
    class Meta:
        verbose_name = _("Node")
        verbose_name_plural = _("Nodes")
        unique_together = ["ref", "language"]

    publisher_location = "p"
    publisher_page_template = "pages/Node/default.pubpage.html"
    publisher_item_template = "pages/Node/default.pubitem.html"

    ref = models.CharField(_("Reference"),
                           max_length=200,
                           blank=True,
                           null=True)
    language = LanguageField(default=models.NOT_PROVIDED, blank=True)
    title = dd.CharField(_("Title"), max_length=250, blank=True)
    # body = dd.BabelTextField(_("Body"), blank=True, format='plain')
    # raw_html = models.BooleanField(_("raw html"), default=False)

    @classmethod
    def lookup_page(cls, ref):
        try:
            return cls.objects.get(ref=ref, language=get_language())
        except cls.DoesNotExist:
            pass

    @classmethod
    def get_dashboard_objects(cls, user):
        # print("20210114 get_dashboard_objects()", get_language())
        qs = Page.objects.filter(parent__isnull=True, language=get_language())
        for node in qs.order_by("seqno"):
            yield node

    def get_absolute_url(self, **kwargs):
        if self.ref:
            if self.ref != 'index':
                return dd.plugins.pages.build_plain_url(self.ref, **kwargs)
        return dd.plugins.pages.build_plain_url(**kwargs)

    def get_sidebar_caption(self):
        if self.title:
            return self.title
        if self.ref:
            return self.ref
        return str(self.id)

        #~ if self.ref or self.parent:
        #~ return self.ref
        #~ return unicode(_('Home'))

    def get_sidebar_item(self, request, other):
        kw = dict()
        add_user_language(kw, request)
        url = self.get_absolute_url(**kw)
        a = E.a(self.get_sidebar_caption(), href=url)
        if self == other:
            return E.li(a, **{'class': 'active'})
        return E.li(a)

    def get_sidebar_html(self, request):
        items = []
        #~ loop over top-level nodes
        for n in Page.objects.filter(parent__isnull=True).order_by('seqno'):
            #~ items += [li for li in n.get_sidebar_items(request,self)]
            items.append(n.get_sidebar_item(request, self))
            if self.is_parented(n):
                children = []
                for ch in n.children.order_by('seqno'):
                    children.append(ch.get_sidebar_item(request, self))
                if len(children):
                    items.append(E.ul(*children, **{'class': 'nav nav-list'}))

        e = E.ul(*items, **{'class': 'nav nav-list'})
        return tostring_pretty(e)

    def get_sidebar_menu(self, request):
        qs = Page.objects.filter(parent__isnull=True, language=get_language())
        #~ qs = self.children.all()
        yield ('/', 'index', str(_('Home')))
        #~ yield ('/downloads/', 'downloads', 'Downloads')
        #~ yield ('/about', 'about', 'About')
        #~ if qs is not None:
        for obj in qs.order_by("seqno"):
            if obj.ref and obj.title:
                yield ('/' + obj.ref, obj.ref, obj.title)
示例#15
0
文件: models.py 项目: forexblog/xl
class Address(AddressLocation):
    class Meta:
        app_label = 'addresses'
        verbose_name = _("Address")
        verbose_name_plural = _("Addresses")

    quick_search_fields = "partner__name city__name street"

    data_source = DataSources.field(editable=False, default='manually')
    # address_type = AddressTypes.field(blank=True, null=True)
    address_type = AddressTypes.field(default='official')
    partner = dd.ForeignKey(dd.plugins.addresses.partner_model,
                            related_name='addresses_by_partner')
    remark = dd.CharField(_("Remark"), max_length=50, blank=True)

    primary = models.BooleanField(_("Primary"), default=False)

    allow_cascaded_delete = ['partner']

    def __str__(self):
        return self.address_location(', ')

    def after_ui_save(self, ar, cw):
        super(Address, self).after_ui_save(ar, cw)
        mi = self.partner
        if mi is None:
            return
        if self.primary:
            for o in mi.addresses_by_partner.exclude(id=self.id).filter(
                    primary=True):
                o.primary = False
                o.save()
                ar.set_response(refresh_all=True)
        mi.sync_primary_address(ar.request)

    def living_at_text(self):
        lines = list(self.address_location_lines())
        return self.address_type.living_text + ' ' + ', '.join(lines)

    @classmethod
    def setup_parameters(cls, fields):
        fields.update(
            place=dd.ForeignKey('countries.Place', blank=True, null=True))
        super(Address, cls).setup_parameters(fields)

    @classmethod
    def get_request_queryset(cls, ar, **filter):
        qs = super(Address, cls).get_request_queryset(ar, **filter)
        pv = ar.param_values
        if pv.place:
            qs = qs.filter(city=pv.place)
        return qs

    @classmethod
    def get_title_tags(self, ar):
        for t in super(Address, self).get_title_tags(ar):
            yield t
        pv = ar.param_values
        if pv.place:
            yield str(pv.place)

    @classmethod
    def get_simple_parameters(cls):
        for p in super(Address, cls).get_simple_parameters():
            yield p
        yield 'partner'
        yield 'address_type'
示例#16
0
class Commit(Created, Authored):
    """A **Commit** is a git commit sha and other relevant data.

    .. attribute:: repository

        The repository where this change was committed.

    .. attribute:: url

        Url pointing to the details for this commit on Github.

    .. attribute:: git_user

        The Github user who commited this commit.
        If there is a user who was linked to this commit via
        user.User.github_username this will be blank.

        Otherwise it will contain the username of the unknown commiter

    .. attribute:: user

        User who commited this commit to github, uses user.User.github_username

    .. attribute:: sha

        Primary Key
        40 Character sha1 hash for the commit

    .. attribute:: summary

        The summary of the commit.
    """
    class Meta:
        app_label = 'github'
        verbose_name = _("Commit")
        verbose_name_plural = _('Commits')
        abstract = dd.is_abstract_model(__name__, 'Commit')

    repository = dd.ForeignKey(Repository,
                               verbose_name=_("Repository"),
                               related_name="commits")

    user = dd.ForeignKey('users.User',
                         verbose_name=_("Author"),
                         related_name="%(app_label)s_%(class)s_set_by_user",
                         blank=True,
                         null=True)
    ticket = dd.ForeignKey('tickets.Ticket',
                           verbose_name=_("Ticket"),
                           related_name="Commits",
                           blank=True,
                           null=True)

    git_user = dd.CharField(_("Github User Name"),
                            blank=True,
                            max_length=39,
                            editable=False)
    commiter_name = dd.CharField(
        _("Git User Name"),
        blank=True,
        max_length=100,
    )
    sha = dd.CharField(
        _("Sha Hash"),
        max_length=40,
        # primary_key=True, #Causes Issues with extjs6
        unique=True,
        editable=False)
    url = dd.models.URLField(_("Commit page"), max_length=255, editable=False)
    description = dd.models.TextField(
        _("Description"),
        editable=False,
        blank=True,
        null=True,
    )
    summary = dd.CharField(_("Summary"),
                           editable=False,
                           blank=True,
                           null=True,
                           max_length=100)
    comment = dd.CharField(_("Comment"), blank=True, null=True, max_length=255)

    unassignable = dd.models.BooleanField(_("Unassignable"),
                                          default=False,
                                          editable=True)
    data = dd.models.TextField(_("Raw json"))

    def get_overview_elems(self, ar):
        return [E.a(self.sha, href=self.url)]

    # @dd.displayfield(_("GH diff"))
    # def clickable_url(self, obj, ar):
    #     return E.a(self.sha, href=self.url)

    @classmethod
    def from_api(cls, d, repo):
        """
        :param d: dict representing the commit from the api
        :param repo: repo which this commit is from
        :return: Commit instance, without doing session lookup, just parses json return values and returns instance.
        """
        try:
            c = Commit.objects.get(sha=d['sha'])
            id = c.id
        except Commit.DoesNotExist:
            id = None

        params = dict(
            id=id,
            repository=repo,
            user=None,
            ticket=None,
            git_user=d['committer']['login']
            if d['committer'] is not None else "",
            commiter_name=d['commit']['committer']['name'],
            sha=d['sha'],
            url=d['html_url'],
            created=timezone.utc.localize(
                timezone.datetime.strptime(d['commit']['committer']['date'],
                                           "%Y-%m-%dT%H:%M:%SZ")),
            description=d['commit']['message'],
            summary=d['commit']['message'].split('\n', 1)[0][0:100],
            comment="",
            data=json.dumps(d),
            unassignable=False,
        )
        return cls(**params)
示例#17
0
class Repository(dd.Model):
    """
    A **Repository** is a git username and repo name, along with an
    o-auth token to allow for more then 60 requests to github an hour.

    .. attribute:: user_name

        Github username.

    .. attribute:: repo_name

        Name of Repo belonging to user_name

    .. attribute:: o_auth

        Access token to be used with github's api,
        https://github.com/settings/tokens/new
        For public repos create a token with no scope.
        For private repos the token must have repo commit access,
        because github doesn't provide a way for a token to have
        read only status, we recommend not using this module with
        private repos unless you are sure that the token is secure.
    """
    class Meta:
        app_label = 'github'
        verbose_name = _("Repository")
        verbose_name_plural = _('Repositories')
        abstract = dd.is_abstract_model(__name__, 'Repository')

    user_name = dd.CharField(_("User Name"), max_length=39)
    repo_name = dd.CharField(_("Repository Name"), max_length=100)
    o_auth = dd.CharField(_("OAuth Token"), max_length=40, blank=True)

    import_all_commits = Import_all_commits()
    import_new_commits = Import_new_commits()
    update_all_repos = Update_all_repos()

    def __str__(self):
        return "%s:%s" % (self.user_name, self.repo_name)

    @dd.displayfield(_("Url"))
    def url(self, ar):
        return "https://github.com/%s/%s/" % (self.user_name, self.repo_name)

    def api_url(self):
        return "https://api.github.com/repos/%s/%s/" % (self.user_name,
                                                        self.repo_name)

    @dd.displayfield(_("Number Of commits"))
    def size(self, ar):
        return self.commits.count()

    def github_api_get_all_comments(self, sha=None):
        """

        :return: yields json commits of comments for this repo's master branch untill none are left
        """
        parms = {'page': 1, 'per_page': 100}
        if self.o_auth:
            parms['access_token'] = self.o_auth

        if sha is not None:
            parms['sha'] = sha
        r = requests.get(self.api_url() + 'commits', parms)
        content = json.loads(r.content.decode())
        for c in content:
            yield c
        while 'rel="next"' in r.headers.get('link', ""):
            parms['page'] += 1
            r = requests.get(self.api_url() + 'commits', parms)
            content = json.loads(r.content.decode())
            for c in content:
                yield c

    def get_overview_elems(self, ar):
        return [E.a(self.repo_name, href=self.url)]
示例#18
0
        params = dict(
            id=id,
            repository=repo,
            user=None,
            ticket=None,
            git_user=d['committer']['login']
            if d['committer'] is not None else "",
            commiter_name=d['commit']['committer']['name'],
            sha=d['sha'],
            url=d['html_url'],
            created=timezone.utc.localize(
                timezone.datetime.strptime(d['commit']['committer']['date'],
                                           "%Y-%m-%dT%H:%M:%SZ")),
            description=d['commit']['message'],
            summary=d['commit']['message'].split('\n', 1)[0][0:100],
            comment="",
            data=json.dumps(d),
            unassignable=False,
        )
        return cls(**params)


dd.inject_field("users.User", 'github_username',
                dd.CharField(_("Github Username"), max_length=39, blank=True))


@dd.schedule_often(3600)
def update_all_repos():
    Repository.update_all_repos.run_from_code(
        rt.models.github.Repositories.request())
示例#19
0
class Address(AddressLocation):
    """Inherits fields from
    :class:`lino_xl.lib.countries.CountryRegionCity` (country, region,
    city. zip_code) and :class:`lino_xl.lib.contacts.AddresssLocation`
    (street, street_no, ...)

    .. attribute:: partner

    .. attribute:: address_type

    .. attribute:: data_source
    
        Pointer to :class:`choicelists.DataSources`.

        Specifies how this information entered into our database.

    .. attribute:: primary
    
        Whether this address is the primary address of its owner.
        Setting this field will automatically uncheck any previousl
        primary addresses and update the owner's address fields.

    """
    class Meta:
        app_label = 'addresses'
        verbose_name = _("Address")
        verbose_name_plural = _("Addresses")

    data_source = DataSources.field(editable=False,
                                    default=DataSources.manually.as_callable)
    # address_type = AddressTypes.field(blank=True, null=True)
    address_type = AddressTypes.field(
        default=AddressTypes.official.as_callable)
    partner = dd.ForeignKey('contacts.Partner',
                            related_name='addresses_by_partner')
    remark = dd.CharField(_("Remark"), max_length=50, blank=True)

    primary = models.BooleanField(
        _("Primary"),
        default=False,
        help_text=_("Checking this field will automatically uncheck any "
                    "previous primary addresses and update "
                    "the partner's address data fields."))

    allow_cascaded_delete = ['partner']

    def __str__(self):
        return self.address_location(', ')

    def after_ui_save(self, ar, cw):
        super(Address, self).after_ui_save(ar, cw)
        mi = self.partner
        if mi is None:
            return
        if self.primary:
            for o in mi.addresses_by_partner.exclude(id=self.id):
                if o.primary:
                    o.primary = False
                    o.save()
                    ar.set_response(refresh_all=True)
        mi.sync_primary_address(ar.request)

    def living_at_text(self):
        lines = list(self.address_location_lines())
        return self.address_type.living_text + ' ' + ', '.join(lines)
示例#20
0
class ChatMessage(UserAuthored, Created, Previewable):
    class Meta(object):
        app_label = 'chat'
        verbose_name = _("Chat message")
        verbose_name_plural = _("Chat messages")
        ordering = ['created', 'id']

    # message_type = MessageTypes.field(default="change")

    seen = models.DateTimeField(_("seen"), null=True, editable=False)
    sent = models.DateTimeField(_("sent"), null=True, editable=False)
    group = dd.ForeignKey('chat.ChatGroup',
                          blank=True,
                          null=True,
                          verbose_name=_(u'Group'),
                          related_name="messages")
    hash = dd.CharField(_("Hash"), max_length=25, null=True, blank=True)

    # body = dd.RichTextField(_("Body"), editable=False, format='html')

    def __str__(self):
        return "{}: {}".format(self.user, self.body)

        # return _("About {0}").format(self.owner)

    # return self.message
    # return _("Notify {0} about change on {1}").format(
    #     self.user, self.owner)

    def send_global_message(self):
        # message = {
        #     "id": self.pk,
        #     # "subject": str(self.subject),
        #     "user": self.user,
        #     "body": html2text(self.body),
        #     "created": self.created.strftime("%a %d %b %Y %H:%M"),
        # }
        logger.info("Sending Message %s:#%s" % (self.user, self.pk))
        send_global_chat(self)
        # self.sent = timezone.now()
        # self.save()

    @classmethod
    def markAsSeen(Cls, data):
        group_id = data['body'][0]
        # msg_ids = [chat[3] for chat in data['body'][1]]
        ChatProps.objects.filter(chat__group__pk=group_id,
                                 user=data['user'],
                                 seen__isnull=True).update(seen=timezone.now())

    @classmethod
    def onRecive(Cls, data):
        print(data)
        args = dict(user=data['user'],
                    body=data['body']['body'],
                    group_id=data['body']['group_id'],
                    hash=data['body']['hash'])
        newMsg = Cls(**args)
        newMsg.full_clean()
        newMsg.save()
        newMsg.after_ui_create()
        newMsg.send_global_message()

    def after_ui_create(self, *args):
        for sub in self.group.ChatGroupsMembers.all().select_related("user"):
            props = ChatProps(chat=self, user=sub.user)
            props.full_clean()
            props.save()

        # super(ChatMessage, self).after_ui_save()

    @dd.action(_("ChatsMsg"))
    def getChats(self, ar):
        # return ar.success(rows=[])

        # doto, have work.
        last_ten_seen = ChatProps.objects.filter(seen__isnull=False).order_by(
            '-created').select_related("chat")[:10]
        unseen = ChatProps.objects.filter(
            user=ar.get_user(), chat=self,
            seen__isnull=True).order_by('-created').select_related("chat")

        last_ten_in_ascending_order = reversed(last_ten_seen)
        unseen_in_ascending_order = reversed(unseen)
        rows = [[(c.chat.user.username, ar.parse_memo(c.chat.body),
                  c.chat.created, c.seen, c.chat.pk, c.chat.user.id)
                 for c in last_ten_in_ascending_order],
                [(c.chat.user.username, ar.parse_memo(c.chat.body),
                  c.chat.created, c.seen, c.chat.pk, c.chat.user.id)
                 for c in unseen_in_ascending_order]]
        return ar.success(rows=rows)