arthexis 0.1.20__py3-none-any.whl → 0.1.22__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of arthexis might be problematic. Click here for more details.

@@ -2,7 +2,6 @@ from utils.sites import get_site
2
2
  from django.urls import Resolver404, resolve
3
3
  from django.conf import settings
4
4
  from pathlib import Path
5
- from types import SimpleNamespace
6
5
  from nodes.models import Node
7
6
  from core.models import Reference
8
7
  from core.reference_utils import filter_visible_references
@@ -49,7 +48,6 @@ def nav_links(request):
49
48
  modules = []
50
49
 
51
50
  valid_modules = []
52
- datasette_enabled = False
53
51
  current_module = None
54
52
  user = getattr(request, "user", None)
55
53
  user_is_authenticated = getattr(user, "is_authenticated", False)
@@ -117,15 +115,6 @@ def nav_links(request):
117
115
  ):
118
116
  current_module = module
119
117
 
120
- datasette_lock = Path(settings.BASE_DIR) / "locks" / "datasette.lck"
121
- if datasette_lock.exists():
122
- datasette_enabled = True
123
- datasette_module = SimpleNamespace(
124
- menu_label="Data",
125
- path="/data/",
126
- enabled_landings=[SimpleNamespace(path="/data/", label="Datasette")],
127
- )
128
- valid_modules.append(datasette_module)
129
118
 
130
119
  valid_modules.sort(key=lambda m: m.menu_label.lower())
131
120
 
@@ -159,5 +148,4 @@ def nav_links(request):
159
148
  "nav_modules": valid_modules,
160
149
  "favicon_url": favicon_url,
161
150
  "header_references": header_references,
162
- "datasette_enabled": datasette_enabled,
163
151
  }
pages/forms.py CHANGED
@@ -171,15 +171,35 @@ class UserStoryForm(forms.ModelForm):
171
171
  "comments": forms.Textarea(attrs={"rows": 4, "maxlength": 400}),
172
172
  }
173
173
 
174
- def __init__(self, *args, **kwargs):
174
+ def __init__(self, *args, user=None, **kwargs):
175
+ self.user = user
175
176
  super().__init__(*args, **kwargs)
176
- self.fields["name"].required = False
177
- self.fields["name"].widget.attrs.update(
178
- {
179
- "maxlength": 40,
180
- "placeholder": _("Name, email or pseudonym"),
181
- }
182
- )
177
+
178
+ if user is not None and user.is_authenticated:
179
+ name_field = self.fields["name"]
180
+ name_field.required = False
181
+ name_field.label = _("Username")
182
+ name_field.initial = (user.get_username() or "")[:40]
183
+ name_field.widget.attrs.update(
184
+ {
185
+ "maxlength": 40,
186
+ "readonly": "readonly",
187
+ }
188
+ )
189
+ else:
190
+ self.fields["name"] = forms.EmailField(
191
+ label=_("Email address"),
192
+ max_length=40,
193
+ required=True,
194
+ widget=forms.EmailInput(
195
+ attrs={
196
+ "maxlength": 40,
197
+ "placeholder": _("name@example.com"),
198
+ "autocomplete": "email",
199
+ "inputmode": "email",
200
+ }
201
+ ),
202
+ )
183
203
  self.fields["take_screenshot"].initial = True
184
204
  self.fields["rating"].widget = forms.RadioSelect(
185
205
  choices=[(i, str(i)) for i in range(1, 6)]
@@ -194,5 +214,8 @@ class UserStoryForm(forms.ModelForm):
194
214
  return comments
195
215
 
196
216
  def clean_name(self):
217
+ if self.user is not None and self.user.is_authenticated:
218
+ return (self.user.get_username() or "")[:40]
219
+
197
220
  name = (self.cleaned_data.get("name") or "").strip()
198
221
  return name[:40]
pages/models.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import logging
3
+ from datetime import timedelta
3
4
  from pathlib import Path
4
5
 
5
6
  from django.db import models
@@ -7,10 +8,11 @@ from django.db.models import Q
7
8
  from core.entity import Entity
8
9
  from core.models import Lead, SecurityGroup
9
10
  from django.contrib.sites.models import Site
10
- from nodes.models import NodeRole
11
+ from nodes.models import ContentSample, NodeRole
11
12
  from django.apps import apps as django_apps
13
+ from django.utils import timezone
12
14
  from django.utils.text import slugify
13
- from django.utils.translation import gettext, gettext_lazy as _
15
+ from django.utils.translation import gettext, gettext_lazy as _, get_language_info
14
16
  from importlib import import_module
15
17
  from django.urls import URLPattern
16
18
  from django.conf import settings
@@ -490,6 +492,14 @@ class ViewHistory(Entity):
490
492
  def __str__(self) -> str: # pragma: no cover - simple representation
491
493
  return f"{self.method} {self.path} ({self.status_code})"
492
494
 
495
+ @classmethod
496
+ def purge_older_than(cls, *, days: int) -> int:
497
+ """Delete history entries recorded more than ``days`` days ago."""
498
+
499
+ cutoff = timezone.now() - timedelta(days=days)
500
+ deleted, _ = cls.objects.filter(visited_at__lt=cutoff).delete()
501
+ return deleted
502
+
493
503
 
494
504
  class Favorite(Entity):
495
505
  user = models.ForeignKey(
@@ -500,9 +510,11 @@ class Favorite(Entity):
500
510
  content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
501
511
  custom_label = models.CharField(max_length=100, blank=True)
502
512
  user_data = models.BooleanField(default=False)
513
+ priority = models.IntegerField(default=0)
503
514
 
504
515
  class Meta:
505
516
  unique_together = ("user", "content_type")
517
+ ordering = ["priority", "pk"]
506
518
 
507
519
 
508
520
  class UserStory(Lead):
@@ -545,6 +557,19 @@ class UserStory(Lead):
545
557
  blank=True,
546
558
  help_text=_("Link to the GitHub issue created for this feedback."),
547
559
  )
560
+ screenshot = models.ForeignKey(
561
+ ContentSample,
562
+ on_delete=models.SET_NULL,
563
+ blank=True,
564
+ null=True,
565
+ related_name="user_stories",
566
+ help_text=_("Screenshot captured for this feedback."),
567
+ )
568
+ language_code = models.CharField(
569
+ max_length=15,
570
+ blank=True,
571
+ help_text=_("Language selected when the feedback was submitted."),
572
+ )
548
573
 
549
574
  class Meta:
550
575
  ordering = ["-submitted_at"]
@@ -590,6 +615,21 @@ class UserStory(Lead):
590
615
  f"**Screenshot requested:** {screenshot_requested}",
591
616
  ]
592
617
 
618
+ language_code = (self.language_code or "").strip()
619
+ if language_code:
620
+ normalized = language_code.replace("_", "-").lower()
621
+ try:
622
+ info = get_language_info(normalized)
623
+ except KeyError:
624
+ language_display = ""
625
+ else:
626
+ language_display = info.get("name_local") or info.get("name") or ""
627
+
628
+ if language_display:
629
+ lines.append(f"**Language:** {language_display} ({normalized})")
630
+ else:
631
+ lines.append(f"**Language:** {normalized}")
632
+
593
633
  if self.submitted_at:
594
634
  lines.append(f"**Submitted at:** {self.submitted_at.isoformat()}")
595
635