Skip to content

Commit 4634ce2

Browse files
authored
Merge pull request #66 from aboutcode-org/ux-improvements
UI/UX Improvements for Deployment
2 parents 615c69c + 6ec0335 commit 4634ce2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1218
-5630
lines changed

.dockerignore

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
eggs/
15+
.eggs/
16+
lib/
17+
lib64/
18+
parts/
19+
sdist/
20+
var/
21+
wheels/
22+
*.egg-info/
23+
.installed.cfg
24+
*.egg
25+
26+
27+
# Installer logs
28+
pip-log.txt
29+
pip-delete-this-directory.txt
30+
pip-selfcheck.json
31+
32+
# Unit test / coverage reports
33+
htmlcov/
34+
.tox/
35+
.coverage
36+
.coverage.*
37+
.cache
38+
coverage.xml
39+
*.cover
40+
41+
# Translations
42+
*.mo
43+
*.pot
44+
45+
# Django stuff:
46+
*.log
47+
local_settings.py
48+
49+
# Sphinx
50+
docs/_build
51+
docs/bin
52+
docs/build
53+
docs/include
54+
docs/Lib
55+
doc/pyvenv.cfg
56+
pyvenv.cfg
57+
58+
# PyBuilder
59+
target/
60+
61+
# Jupyter Notebook
62+
.ipynb_checkpoints
63+
64+
# pyenv and pip
65+
.python-version
66+
pyvenv.cfg
67+
bin/
68+
69+
# Environments
70+
.venv
71+
env/
72+
venv/
73+
ENV/
74+
75+
76+
# mypy
77+
.mypy_cache/
78+
79+
80+
# Database
81+
*.sqlite3*
82+
83+
# Staticfiles
84+
staticfiles/
85+
86+
# virtualenv
87+
bin
88+
include
89+
lib64
90+
share
91+
Pipfile
92+
93+
# editors
94+
.vscode
95+
# PyCharm
96+
.idea/
97+
98+
# pytest
99+
.pytest_cache
100+
101+
102+
# Various junk and temp files
103+
.DS_Store
104+
*~
105+
.*.sw[po]
106+
.build
107+
.ve
108+
*.bak
109+
/.cache/
110+
/tmp/
111+
112+
# pyenv
113+
/.python-version
114+
/man/
115+
/.pytest_cache/
116+
lib64
117+
tcl
118+
119+
# Ignore Jupyter Notebook related temp files
120+
.ipynb_checkpoints/

fedcode/forms.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ class CreateGitRepoForm(forms.ModelForm):
2020
class Meta:
2121
model = Repository
2222
fields = ["url"]
23-
help_texts = {
24-
"url": None,
25-
}
2623

2724
def __init__(self, *args, **kwargs):
2825
super(CreateGitRepoForm, self).__init__(*args, **kwargs)
2926
self.fields["url"].widget.attrs.update(
30-
{"class": "input mb-5", "placeholder": "https://github.com/nexB/vulnerablecode-data"}
27+
{"class": "input", "placeholder": "https://github.com/nexB/vulnerablecode-data"}
3128
)
29+
self.fields["url"].help_text = ""
30+
self.fields["url"].label = ""
3231

3332

3433
class CreateNoteForm(forms.ModelForm):
@@ -39,9 +38,10 @@ class Meta:
3938
def __init__(self, *args, **kwargs):
4039
super(CreateNoteForm, self).__init__(*args, **kwargs)
4140
self.fields["content"].widget.attrs.update(
42-
{"class": "textarea", "placeholder": "Add a note...", "rows": 5}
41+
{"class": "textarea", "placeholder": "Comment...", "rows": 5}
4342
)
4443
self.fields["content"].label = ""
44+
self.fields["content"].help_text = ""
4545

4646

4747
class ReviewStatusForm(forms.ModelForm):
@@ -109,9 +109,8 @@ class SearchPackageForm(forms.Form):
109109
label=False,
110110
widget=forms.TextInput(
111111
attrs={
112-
"placeholder": "Please enter a valid purl ex: pkg:maven/org.apache.commons/io",
113-
"class": "input is-rounded",
114-
"style": "width: 90%;",
112+
"placeholder": "Search a package...",
113+
"class": "input ",
115114
},
116115
),
117116
)
@@ -137,9 +136,8 @@ class SearchRepositoryForm(forms.Form):
137136
label=False,
138137
widget=forms.TextInput(
139138
attrs={
140-
"placeholder": "Please Enter a Repository URL ex: https://github.com/nexB/vulnerablecode-data",
141-
"class": "input is-rounded",
142-
"style": "width: 90%;",
139+
"placeholder": "Search a repository...",
140+
"class": "input",
143141
},
144142
),
145143
)

fedcode/middleware.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# FederatedCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/nexB/federatedcode for support or download.
7+
# See https://aboutcode.org for more information about AboutCode.org OSS projects.
8+
#
9+
10+
import zoneinfo
11+
12+
from django.utils import timezone
13+
14+
15+
class TimezoneMiddleware:
16+
def __init__(self, get_response):
17+
self.get_response = get_response
18+
19+
def __call__(self, request):
20+
try:
21+
# Activate local timezone for user using cookies
22+
tzname = request.COOKIES.get("user_timezone")
23+
if tzname:
24+
timezone.activate(zoneinfo.ZoneInfo(tzname))
25+
else:
26+
timezone.deactivate()
27+
except Exception as e:
28+
timezone.deactivate()
29+
30+
return self.get_response(request)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 5.1.2 on 2024-12-27 17:48
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("fedcode", "0004_alter_vulnerability_unique_together"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="person",
15+
name="avatar",
16+
),
17+
]

fedcode/models.py

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class RemoteActor(models.Model):
5050
help_text="A field to track when remote actor are updated",
5151
)
5252

53+
@property
54+
def safe_url(self):
55+
return f"{self.url.rstrip('/')}/"
56+
5357

5458
class Actor(models.Model):
5559
"""
@@ -227,6 +231,11 @@ def reputation_value(self):
227231
def absolute_url(self):
228232
return full_reverse("note-page", self.id)
229233

234+
@property
235+
def acct_avatar(self):
236+
person = Person.objects.get(user__username=self.username)
237+
return person.avatar
238+
230239
@property
231240
def to_ap(self):
232241
return {
@@ -290,6 +299,10 @@ def __str__(self):
290299
def followers_count(self):
291300
return Follow.objects.filter(package=self).count()
292301

302+
@property
303+
def notes_count(self):
304+
return Note.objects.filter(acct=self.acct).count()
305+
293306
@property
294307
def followers(self):
295308
return Follow.objects.filter(package=self).values("person_id")
@@ -350,16 +363,9 @@ def to_ap(self):
350363

351364
class Person(Actor):
352365
"""
353-
A person is a user can follow pacakge or just vote or create a notes
366+
A person is a user can follow package or just vote or create a notes
354367
"""
355368

356-
avatar = models.ImageField(
357-
upload_to="uploads/",
358-
help_text="",
359-
default="favicon-16x16.png",
360-
null=True,
361-
)
362-
363369
user = models.OneToOneField(
364370
User,
365371
null=True,
@@ -391,13 +397,24 @@ class Meta:
391397
),
392398
]
393399

400+
@property
401+
def avatar(self):
402+
from hashlib import sha256
403+
404+
email = ""
405+
if self.user and (email := self.user.email):
406+
email = email.strip().lower()
407+
408+
gravatar = sha256(email.encode("utf-8")).hexdigest()
409+
return f"https://gravatar.com/avatar/{gravatar}"
410+
394411
@property
395412
def local(self):
396413
return bool(self.user)
397414

398415
@property
399416
def avatar_absolute_url(self):
400-
return f'{"https://"}{FEDERATEDCODE_DOMAIN}{self.avatar.url}'
417+
return self.avatar
401418

402419
# TODO raise error if the user doesn't have a user or remote actor
403420
@property
@@ -425,13 +442,13 @@ def absolute_url_ap(self):
425442
@property
426443
def inbox_url(self):
427444
if not self.local:
428-
return urljoin(self.remote_actor.url, "inbox")
445+
return urljoin(self.remote_actor.safe_url, "inbox")
429446
return full_reverse("user-inbox", self.user.username)
430447

431448
@property
432449
def outbox_url(self):
433450
if not self.local:
434-
return urljoin(self.remote_actor.url, "outbox")
451+
return urljoin(self.remote_actor.safe_url, "outbox")
435452
return full_reverse("user-outbox", self.user.username)
436453

437454
@property
@@ -443,7 +460,7 @@ def key_id(self):
443460
if self.user:
444461
return full_reverse("user-ap-profile", self.user.username) + "#main-key"
445462
else:
446-
return self.remote_actor.url + "#main-key"
463+
return self.remote_actor.safe_url + "#main-key"
447464

448465
@property
449466
def to_ap(self):
@@ -604,7 +621,7 @@ class Vulnerability(models.Model):
604621
)
605622

606623
class Meta:
607-
unique_together = ('id', 'repo')
624+
unique_together = ("id", "repo")
608625

609626
@property
610627
def absolute_url(self):

fedcode/pipes/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020

2121
def create_note(pkg, note_dict):
22+
# TODO: also take argument for source of the note ideally github blob for
23+
# for file.
2224
note, _ = Note.objects.get_or_create(acct=pkg.acct, content=saneyaml.dump(note_dict))
2325
pkg.notes.add(note)
2426
create_activity = CreateActivity(actor=pkg.to_ap, object=note.to_ap)

fedcode/templates/403.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends "base.html" %}
2+
3+
{% block title %}
4+
Permission Denied
5+
{% endblock %}
6+
7+
{% block content %}
8+
<section class="hero is-large is-link">
9+
<div class="hero-body">
10+
<div class="container has-text-centered">
11+
<h1 class="title is-1 pb-2">
12+
Permission Denied
13+
</h1>
14+
<p class="subtitle is-4">
15+
You do not have permission to access this page.
16+
</p>
17+
<a href="{% url 'purl-list' %}" class="button is-dark">Explore available packages</a>
18+
</div>
19+
</div>
20+
</section>
21+
{% endblock %}

fedcode/templates/404.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends "base.html" %}
2+
3+
{% block title %}
4+
Page Not Found
5+
{% endblock %}
6+
7+
{% block content %}
8+
<section class="hero is-large is-link">
9+
<div class="hero-body">
10+
<div class="container has-text-centered">
11+
<h1 class="title is-1 pb-2">
12+
404 - Page Not Found
13+
</h1>
14+
<p class="subtitle is-4">
15+
Sorry, the page you're looking for does not exist.
16+
</p>
17+
<a href="{% url 'purl-list' %}" class="button is-dark">Explore available packages</a>
18+
</div>
19+
</div>
20+
</section>
21+
{% endblock %}

0 commit comments

Comments
 (0)