Skip to content

Commit 9f593f2

Browse files
authored
Merge pull request #5916 from saadmk11/fix-build-ux
Update build list and detail page UX
2 parents ddf5259 + 8310e58 commit 9f593f2

File tree

13 files changed

+284
-47
lines changed

13 files changed

+284
-47
lines changed

readthedocs/api/v2/serializers.py

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class BuildSerializer(serializers.ModelSerializer):
118118
version_slug = serializers.ReadOnlyField(source='version.slug')
119119
docs_url = serializers.ReadOnlyField(source='version.get_absolute_url')
120120
state_display = serializers.ReadOnlyField(source='get_state_display')
121+
commit_url = serializers.ReadOnlyField(source='get_commit_url')
121122
# Jsonfield needs an explicit serializer
122123
# https://github.com/dmkoch/django-jsonfield/issues/188#issuecomment-300439829
123124
config = serializers.JSONField(required=False)

readthedocs/builds/constants.py

+3
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,6 @@
8787
'description': 'The build succeeded!',
8888
},
8989
}
90+
91+
GITHUB_EXTERNAL_VERSION_NAME = 'Pull Request'
92+
GENERIC_EXTERNAL_VERSION_NAME = 'External Version'

readthedocs/builds/models.py

+102-20
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@
2020
from readthedocs.config import LATEST_CONFIGURATION_VERSION
2121
from readthedocs.core.utils import broadcast
2222
from readthedocs.projects.constants import (
23+
BITBUCKET_COMMIT_URL,
2324
BITBUCKET_URL,
25+
GITHUB_COMMIT_URL,
2426
GITHUB_URL,
27+
GITHUB_PULL_REQUEST_URL,
28+
GITHUB_PULL_REQUEST_COMMIT_URL,
29+
GITLAB_COMMIT_URL,
2530
GITLAB_URL,
2631
PRIVACY_CHOICES,
2732
PRIVATE,
@@ -36,6 +41,8 @@
3641
BUILD_STATE_FINISHED,
3742
BUILD_STATE_TRIGGERED,
3843
BUILD_TYPES,
44+
GENERIC_EXTERNAL_VERSION_NAME,
45+
GITHUB_EXTERNAL_VERSION_NAME,
3946
INTERNAL,
4047
LATEST,
4148
NON_REPOSITORY_VERSIONS,
@@ -63,6 +70,7 @@
6370
get_gitlab_username_repo,
6471
)
6572
from readthedocs.builds.version_slug import VersionSlugField
73+
from readthedocs.oauth.models import RemoteRepository
6674

6775

6876
log = logging.getLogger(__name__)
@@ -158,9 +166,20 @@ def vcs_url(self):
158166
"""
159167
Generate VCS (github, gitlab, bitbucket) URL for this version.
160168
161-
Branch/Tag Example: https://github.com/rtfd/readthedocs.org/tree/3.4.2/.
162-
Pull/merge Request Example: https://github.com/rtfd/readthedocs.org/pull/9999/.
169+
Example: https://github.com/rtfd/readthedocs.org/tree/3.4.2/.
170+
External Version Example: https://github.com/rtfd/readthedocs.org/pull/99/.
163171
"""
172+
if self.type == EXTERNAL:
173+
if 'github' in self.project.repo:
174+
user, repo = get_github_username_repo(self.project.repo)
175+
return GITHUB_PULL_REQUEST_URL.format(
176+
user=user,
177+
repo=repo,
178+
number=self.verbose_name,
179+
)
180+
# TODO: Add VCS URL for other Git Providers
181+
return ''
182+
164183
url = ''
165184
if self.slug == STABLE:
166185
slug_url = self.ref
@@ -169,25 +188,12 @@ def vcs_url(self):
169188
else:
170189
slug_url = self.slug
171190

172-
if self.type == EXTERNAL:
173-
if 'github' in self.project.repo:
174-
slug_url = self.verbose_name
175-
url = f'/pull/{slug_url}/'
191+
if ('github' in self.project.repo) or ('gitlab' in self.project.repo):
192+
url = f'/tree/{slug_url}/'
176193

177-
if 'gitlab' in self.project.repo:
178-
slug_url = self.identifier
179-
url = f'/merge_requests/{slug_url}/'
180-
181-
if 'bitbucket' in self.project.repo:
182-
slug_url = self.identifier
183-
url = f'/pull-requests/{slug_url}'
184-
else:
185-
if ('github' in self.project.repo) or ('gitlab' in self.project.repo):
186-
url = f'/tree/{slug_url}/'
187-
188-
if 'bitbucket' in self.project.repo:
189-
slug_url = self.identifier
190-
url = f'/src/{slug_url}'
194+
if 'bitbucket' in self.project.repo:
195+
slug_url = self.identifier
196+
url = f'/src/{slug_url}'
191197

192198
# TODO: improve this replacing
193199
return self.project.repo.replace('git://', 'https://').replace('.git', '') + url
@@ -745,6 +751,60 @@ def get_full_url(self):
745751
)
746752
return full_url
747753

754+
def get_commit_url(self):
755+
"""Return the commit URL."""
756+
repo_url = self.project.repo
757+
if self.is_external:
758+
if 'github' in repo_url:
759+
user, repo = get_github_username_repo(repo_url)
760+
if not user and not repo:
761+
return ''
762+
763+
repo = repo.rstrip('/')
764+
return GITHUB_PULL_REQUEST_COMMIT_URL.format(
765+
user=user,
766+
repo=repo,
767+
number=self.version.verbose_name,
768+
commit=self.commit
769+
)
770+
# TODO: Add External Version Commit URL for other Git Providers
771+
else:
772+
if 'github' in repo_url:
773+
user, repo = get_github_username_repo(repo_url)
774+
if not user and not repo:
775+
return ''
776+
777+
repo = repo.rstrip('/')
778+
return GITHUB_COMMIT_URL.format(
779+
user=user,
780+
repo=repo,
781+
commit=self.commit
782+
)
783+
if 'gitlab' in repo_url:
784+
user, repo = get_gitlab_username_repo(repo_url)
785+
if not user and not repo:
786+
return ''
787+
788+
repo = repo.rstrip('/')
789+
return GITLAB_COMMIT_URL.format(
790+
user=user,
791+
repo=repo,
792+
commit=self.commit
793+
)
794+
if 'bitbucket' in repo_url:
795+
user, repo = get_bitbucket_username_repo(repo_url)
796+
if not user and not repo:
797+
return ''
798+
799+
repo = repo.rstrip('/')
800+
return BITBUCKET_COMMIT_URL.format(
801+
user=user,
802+
repo=repo,
803+
commit=self.commit
804+
)
805+
806+
return ''
807+
748808
@property
749809
def finished(self):
750810
"""Return if build has a finished state."""
@@ -756,6 +816,28 @@ def is_stale(self):
756816
mins_ago = timezone.now() - datetime.timedelta(minutes=5)
757817
return self.state == BUILD_STATE_TRIGGERED and self.date < mins_ago
758818

819+
@property
820+
def is_external(self):
821+
return self.version.type == EXTERNAL
822+
823+
@property
824+
def external_version_name(self):
825+
if self.is_external:
826+
try:
827+
if self.project.remote_repository.account.provider == 'github':
828+
return GITHUB_EXTERNAL_VERSION_NAME
829+
# TODO: Add External Version Name for other Git Providers
830+
except RemoteRepository.DoesNotExist:
831+
log.info('Remote repository does not exist for %s', self.project)
832+
return GENERIC_EXTERNAL_VERSION_NAME
833+
except Exception:
834+
log.exception(
835+
'Unhandled exception raised for %s while getting external_version_name',
836+
self.project
837+
)
838+
return GENERIC_EXTERNAL_VERSION_NAME
839+
return None
840+
759841
def using_latest_config(self):
760842
return int(self.config.get('version', '1')) == LATEST_CONFIGURATION_VERSION
761843

readthedocs/builds/static-src/builds/js/detail.js

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ function BuildDetailView(instance) {
5252
});
5353
self.commit = ko.observable(instance.commit);
5454
self.docs_url = ko.observable(instance.docs_url);
55+
self.commit_url = ko.observable(instance.commit_url);
5556

5657
/* Others */
5758
self.legacy_output = ko.observable(false);
@@ -72,6 +73,7 @@ function BuildDetailView(instance) {
7273
self.length(data.length);
7374
self.commit(data.commit);
7475
self.docs_url(data.docs_url);
76+
self.commit_url(data.commit_url);
7577
var n;
7678
for (n in data.commands) {
7779
var command = data.commands[n];

readthedocs/builds/static/builds/js/detail.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readthedocs/builds/views.py

-15
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,6 @@ def post(self, request, project_slug):
8484

8585
class BuildList(BuildBase, BuildTriggerMixin, ListView):
8686

87-
def get_queryset(self):
88-
# this is used to include only internal version
89-
# builds in the build list page
90-
self.project_slug = self.kwargs.get('project_slug', None)
91-
self.project = get_object_or_404(
92-
Project.objects.protected(self.request.user),
93-
slug=self.project_slug,
94-
)
95-
queryset = Build.objects.public(
96-
user=self.request.user,
97-
project=self.project,
98-
).select_related('project', 'version')
99-
100-
return queryset
101-
10287
def get_context_data(self, **kwargs):
10388
context = super().get_context_data(**kwargs)
10489

readthedocs/projects/constants.py

+20
Original file line numberDiff line numberDiff line change
@@ -325,13 +325,33 @@
325325
'https://github.com/{user}/{repo}/'
326326
'{action}/{version}{docroot}{path}{source_suffix}'
327327
)
328+
GITHUB_COMMIT_URL = (
329+
'https://github.com/{user}/{repo}/'
330+
'commit/{commit}'
331+
)
332+
GITHUB_PULL_REQUEST_URL = (
333+
'https://github.com/{user}/{repo}/'
334+
'pull/{number}'
335+
)
336+
GITHUB_PULL_REQUEST_COMMIT_URL = (
337+
'https://github.com/{user}/{repo}/'
338+
'pull/{number}/commits/{commit}'
339+
)
328340
BITBUCKET_URL = (
329341
'https://bitbucket.org/{user}/{repo}/'
330342
'src/{version}{docroot}{path}{source_suffix}'
331343
)
344+
BITBUCKET_COMMIT_URL = (
345+
'https://bitbucket.org/{user}/{repo}/'
346+
'commits/{commit}'
347+
)
332348
GITLAB_URL = (
333349
'https://gitlab.com/{user}/{repo}/'
334350
'{action}/{version}{docroot}{path}{source_suffix}'
335351
)
352+
GITLAB_COMMIT_URL = (
353+
'https://gitlab.com/{user}/{repo}/'
354+
'commit/{commit}'
355+
)
336356

337357
GITHUB_GIT_PATTERN = 'pull/{id}/head:external-{id}'

readthedocs/projects/views/public.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def get_context_data(self, **kwargs):
9898
context = super().get_context_data(**kwargs)
9999

100100
project = self.get_object()
101-
context['versions'] = Version.objects.public(
101+
context['versions'] = Version.internal.public(
102102
user=self.request.user,
103103
project=project,
104104
)
@@ -274,7 +274,7 @@ def project_versions(request, project_slug):
274274
slug=project_slug,
275275
)
276276

277-
versions = Version.objects.public(
277+
versions = Version.internal.public(
278278
user=request.user,
279279
project=project,
280280
only_active=False,

0 commit comments

Comments
 (0)