Fix table display issues
- Author
- Maarten Vangeneugden
- Date
- Oct. 25, 2023, 5:30 p.m.
- Hash
- b8c45e62a81527ebd6fc1c6750ed2886be59462d
- Parent
- 00cc338301ca90456910abe04fdea8b7ca3f4aff
- Modified files
- GitActions/CommitInfo.py
- templates/gitar/commit.djhtml
- templates/gitar/directory.djhtml
GitActions/CommitInfo.py ¶
5 additions and 8 deletions.
View changes Hide changes
1 |
1 |
# formatted file in a commit. |
2 |
2 |
|
3 |
3 |
# The function returns a list |
4 |
4 |
|
5 |
5 |
# If one line is removed, and one line is added, and both have the same line |
6 |
6 |
# number, then that should be regarded as a changed line, not a removed+added line. |
7 |
7 |
# This holds for each non-broken list of removed+added lines. |
8 |
8 |
|
9 |
9 |
from pydriller.domain.commit import ModificationType |
10 |
10 |
from ..syntax import * |
11 |
11 |
|
12 |
12 |
""" It's a lot of annoying glue code to transform a modified file object into |
13 |
13 |
what we actually want: The data that needs to be passed to the Django template. |
14 |
14 |
This convenience function accepts the modified file object as given by |
15 |
15 |
Pydriller's Commit class, and returns a list of dicts, each dict representing |
16 |
16 |
the information needed to properly present a file diff in the template. |
17 |
17 |
""" |
18 |
18 |
def prepare_and_process(modified_file): |
19 |
19 |
#print(modified_file.source_code) |
20 |
20 |
result = dict() |
21 |
21 |
result["object"] = modified_file # Could come in handy |
22 |
22 |
result["change_type"] = modified_file.change_type |
23 |
23 |
result["html_code_after"] = code_to_HTML( |
24 |
24 |
modified_file.source_code, |
25 |
25 |
modified_file.filename) |
26 |
26 |
result["html_code_before"] = code_to_HTML( |
27 |
27 |
modified_file.source_code_before, |
28 |
28 |
modified_file.filename) |
29 |
29 |
|
30 |
30 |
if modified_file.change_type == ModificationType.ADD: |
31 |
31 |
result["path"] = modified_file.new_path |
32 |
32 |
elif modified_file.change_type == ModificationType.DELETE: |
33 |
33 |
result["path"] = modified_file.old_path |
34 |
34 |
elif modified_file.change_type == ModificationType.RENAME: |
35 |
35 |
result["path"] = modified_file.old_path +" → "+ modified_file.new_path |
36 |
36 |
elif modified_file.change_type == ModificationType.MODIFY: |
37 |
37 |
result["path"] = modified_file.old_path |
38 |
38 |
|
39 |
39 |
added = dict() |
40 |
40 |
deleted = dict() |
41 |
41 |
for number, line in modified_file.diff_parsed["added"]: |
42 |
42 |
added[number] = line |
43 |
43 |
for number, line in modified_file.diff_parsed["deleted"]: |
44 |
44 |
if result["path"] == "Challenge 4/Controller.java": |
45 |
45 |
#print("PING") |
46 |
46 |
pass |
47 |
47 |
deleted[number] = line |
48 |
48 |
if result["path"] == "Challenge 4/Controller.java": |
49 |
49 |
pass |
50 |
50 |
#print("NU CONTROLLER.jAVA") |
51 |
51 |
#print(modified_file.diff_parsed) |
52 |
52 |
#print(deleted) |
53 |
53 |
result["rows"] = process_file( |
54 |
54 |
result["html_code_before"], |
55 |
55 |
result["html_code_after"], |
56 |
56 |
added, |
57 |
57 |
deleted) |
58 |
58 |
|
59 |
59 |
# These three lists are going to be empty if the methods couldn't be detected |
60 |
60 |
deleted, transferred, new = process_methods(modified_file) |
61 |
61 |
if len(deleted) == len(transferred) == len(new) == 0: |
62 |
62 |
result["methods_available"] = False |
63 |
63 |
else: |
64 |
64 |
result["methods_available"] = True |
65 |
65 |
result["deleted_methods"] = deleted |
66 |
66 |
result["transferred_methods"] = transferred |
67 |
67 |
result["new_methods"] = new |
68 |
68 |
return result |
69 |
69 |
|
70 |
70 |
""" Sometimes, the methods in a file can be detected, which adds some nice |
71 |
71 |
information """ |
72 |
72 |
def process_methods(modified_file): |
73 |
73 |
before_methods = modified_file.methods_before |
74 |
74 |
after_methods = modified_file.methods |
75 |
75 |
deleted_methods = [] |
76 |
76 |
transferred_methods = [] |
77 |
77 |
new_methods = [] |
78 |
78 |
|
79 |
79 |
# Finding all transferred and deleted methods |
80 |
80 |
for before_method in before_methods: |
81 |
81 |
transferred = False |
82 |
82 |
for after_method in after_methods: |
83 |
83 |
if before_method.name == after_method.name: # Match found |
84 |
84 |
transferred_methods.append((before_method, after_method)) |
85 |
85 |
transferred = True |
86 |
86 |
break |
87 |
87 |
if not transferred: |
88 |
88 |
deleted_methods.append(before_method) |
89 |
89 |
# Finding all new methods |
90 |
90 |
for after_method in after_methods: |
91 |
91 |
transferred = False |
92 |
92 |
for _, am in transferred_methods: |
93 |
93 |
if after_method == am: |
94 |
94 |
transferred = True |
95 |
95 |
break |
96 |
96 |
if not transferred: |
97 |
97 |
new_methods.append(after_method) |
98 |
98 |
|
99 |
99 |
return deleted_methods, transferred_methods, new_methods |
100 |
100 |
|
101 |
101 |
|
102 |
102 |
def process_file(source_before, source_after, additions, deletions): |
103 |
103 |
rows = [] |
104 |
104 |
# Counting from 1, because source code lines are counted from there |
105 |
105 |
# NOTE: Deletions komen wel degelijk goed binnen |
106 |
106 |
#print("deletions:") |
107 |
107 |
#print(deletions) |
108 |
108 |
before_count = 1 |
109 |
109 |
after_count = 1 |
110 |
110 |
while True: |
111 |
111 |
row = dict() |
112 |
112 |
#print("PROCESS_FILE") |
113 |
113 |
#print(deletions) |
114 |
114 |
#print(additions) |
115 |
115 |
# We check the deletion lines first; if a line was "changed", the |
116 |
116 |
# 'deleted' line needs to be listed first, and after that, the 'added' |
117 |
117 |
# line |
118 |
118 |
#print(str(before_count) + " -- " + str(after_count)) |
119 |
119 |
if before_count in deletions: |
120 |
120 |
row["type"] = "deletion" |
121 |
121 |
row["old_num"] = before_count |
122 |
122 |
# Why source_before[] and not deletions[]? |
123 |
123 |
# Because source_before[] has been processed by Pygments, and thus |
124 |
124 |
# has the syntax highlighting in it. deletions[] is just plain text. |
125 |
125 |
|
126 |
126 |
|
127 |
127 |
# Look, I'm tired at the time of writing, and this line seems to be |
128 |
128 |
# kind of a dick so I'm just gonna try catch it and leave it like |
129 |
129 |
# that for now |
130 |
130 |
#try: |
131 |
131 |
#row["line"] = source_before[before_count] |
132 |
132 |
print(len(source_before)) |
133 |
- | print(before_count) |
134 |
- | if before_count == len(source_before): |
+ |
133 |
#print(before_count) |
+ |
134 |
if before_count == len(source_before): |
135 |
135 |
row["line"] = source_before[-1] |
136 |
136 |
else: |
137 |
137 |
row["line"] = source_before[before_count] |
138 |
138 |
#except: |
139 |
139 |
#pass |
140 |
140 |
|
141 |
141 |
before_count += 1 |
142 |
142 |
elif after_count in additions: |
143 |
143 |
row["type"] = "addition" |
144 |
144 |
row["new_num"] = after_count |
145 |
145 |
# Idem for additions[] |
146 |
146 |
# Look, I'm tired at the time of writing, and this line seems to be |
147 |
- | # kind of a dick so I'm just gonna try catch it and leave it like |
148 |
- | # that for now |
149 |
- | try: |
150 |
- | row["line"] = source_after[after_count] |
+ |
147 |
row["line"] = source_after[-1] |
+ |
148 |
else: |
+ |
149 |
row["line"] = source_after[after_count] |
151 |
150 |
except: |
152 |
- | pass |
153 |
- | after_count += 1 |
154 |
151 |
else: # No change to this particular line |
155 |
152 |
row["old_num"] = before_count |
156 |
153 |
row["new_num"] = after_count |
157 |
154 |
if len(source_before) > before_count: |
158 |
155 |
row["line"] = source_before[before_count] |
159 |
156 |
elif len(source_after) > after_count: |
160 |
157 |
row["line"] = source_after[after_count] |
161 |
158 |
else: # No lines left |
162 |
159 |
break |
163 |
160 |
# If not end of both files, increment both counters anyway |
164 |
161 |
before_count += 1 |
165 |
162 |
after_count += 1 |
166 |
163 |
# Adding the new row to the list of rows |
167 |
164 |
rows.append(row) |
168 |
165 |
return rows |
169 |
166 |
|
170 |
167 |
|
171 |
168 |
|
172 |
169 |
|
173 |
170 |
|
174 |
171 |
|
175 |
172 |
|
176 |
173 |
|
177 |
174 |
templates/gitar/commit.djhtml ¶
5 additions and 0 deletions.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
{% load humanize %} |
3 |
3 |
{% load static %} |
4 |
4 |
|
5 |
5 |
{% block title %}{{ repository_name }} | Gitar{% endblock title %} |
6 |
6 |
|
7 |
7 |
{% block stylesheets %} |
8 |
8 |
{{ block.super }} |
9 |
9 |
<link rel="stylesheet" type="text/css" href="/static/website/syntax.css" /> |
10 |
10 |
<link rel="stylesheet" type="text/css" href="/static/gitar/css/file.css" /> |
11 |
11 |
<style> |
12 |
12 |
table.highlight { |
13 |
13 |
border-collapse: collapse; |
14 |
14 |
} |
15 |
15 |
table.highlight tr { |
16 |
16 |
line-height: 1em; |
17 |
17 |
} |
18 |
18 |
|
19 |
19 |
tr.deletion { |
20 |
20 |
background-color: rgba(255, 0, 0, .1); |
21 |
21 |
} |
22 |
22 |
tr.addition { |
23 |
23 |
background-color: rgba(0, 255, 0, .1); |
24 |
24 |
} |
25 |
25 |
|
+ |
26 |
/* Okay this makes the button stretch but whatever, it's better |
+ |
27 |
than trying to fight the tables */ |
+ |
28 |
display: block; |
+ |
29 |
} |
+ |
30 |
|
26 |
31 |
section { |
27 |
32 |
overflow-x: scroll; |
28 |
33 |
} |
29 |
34 |
|
30 |
35 |
.symbol { |
31 |
36 |
text-align: right; |
32 |
37 |
/*font-weight: bolder;*/ |
33 |
38 |
/* These vendor prefixes are still necessary, yeah...*/ |
34 |
39 |
} |
35 |
40 |
.line-number { |
36 |
41 |
text-align: right; |
37 |
42 |
width: 3em; |
38 |
43 |
-moz-user-select: none; |
39 |
44 |
-webkit-user-select: none; |
40 |
45 |
-ms-user-select: none; |
41 |
46 |
user-select: none; |
42 |
47 |
} |
43 |
48 |
.line-number a { |
44 |
49 |
color: grey; |
45 |
50 |
} |
46 |
51 |
|
47 |
52 |
details span.opened { |
48 |
53 |
display: none; |
49 |
54 |
} |
50 |
55 |
details[open] span.opened { |
51 |
56 |
display: inline; |
52 |
57 |
} |
53 |
58 |
details[open] span.closed { |
54 |
59 |
display: none; |
55 |
60 |
} |
56 |
61 |
</style> |
57 |
62 |
{% endblock stylesheets %} |
58 |
63 |
|
59 |
64 |
{% block description %} |
60 |
65 |
{{ repository_name }} {{ commit.hash|truncatechars:10 }}: {{ commit.msg }} |
61 |
66 |
{% endblock description %} |
62 |
67 |
|
63 |
68 |
{% block header %} |
64 |
69 |
<header> |
65 |
70 |
<label for="nav-drawer-toggle">≡</label> |
66 |
71 |
<h1>{{ repository_name }}</h1> |
67 |
72 |
</header> |
68 |
73 |
{% endblock header %} |
69 |
74 |
|
70 |
75 |
{% block nav %} |
71 |
76 |
<input id="nav-drawer-toggle" type="checkbox" /> |
72 |
77 |
<nav> |
73 |
78 |
<label for="nav-drawer-toggle">🡠</label> |
74 |
79 |
<h2>{{ repository_name }}</h2> |
75 |
80 |
<a class="nav-link" href="{% url 'gitar-index' %}">Gitar | Index</a> |
76 |
81 |
<a class="nav-link" href="{% url 'gitar-repository' repository_name %}">{{ repository_name }} | Index</a> |
77 |
82 |
<a class="nav-link" href="{% url 'about-index' %}">{% translate "Front page" %}</a> |
78 |
83 |
<hr class="half"> |
79 |
84 |
{% for mod_file in modified_files %} |
80 |
85 |
<a class="nav-link" href="#{{ mod_file.path }}">{{ mod_file.path }}</a> |
81 |
86 |
{% endfor %} |
82 |
87 |
</nav> |
83 |
88 |
{% endblock nav %} |
84 |
89 |
|
85 |
90 |
{% block main %} |
86 |
91 |
|
87 |
92 |
<section class="emphasis"> |
88 |
93 |
<h2>{{ first_line }}</h2> |
89 |
94 |
<p>{{ other_lines|safe }}</p> |
90 |
95 |
<dl> |
91 |
96 |
<dt>{% translate "Author" %}</dt> |
92 |
97 |
<dd>{{ commit.author.name }}</dd> |
93 |
98 |
|
94 |
99 |
<dt>{% translate "Date" %}</dt> |
95 |
100 |
<dd>{{ commit.committer_date|date:"DATETIME_FORMAT" }}</dd> |
96 |
101 |
|
97 |
102 |
<dt>{% translate "Hash" %}</dt> |
98 |
103 |
<dd><samp>{{ commit.hash }}</samp></dd> |
99 |
104 |
|
100 |
105 |
{% if commit.parents|length_is:"1" %} |
101 |
106 |
<dt>{% translate "Parent" %}</dt> |
102 |
107 |
{% else %} |
103 |
108 |
<dt>{% translate "Parents" %}</dt> |
104 |
109 |
{% endif %} |
105 |
110 |
{% for parent in commit.parents %} |
106 |
111 |
<dd><samp><a href="{% url "gitar-commit" repository_name parent %}"> |
107 |
112 |
{{ parent }} |
108 |
113 |
</a></samp</dd> |
109 |
114 |
{% endfor %} |
110 |
115 |
|
111 |
116 |
{% if modified_files|length_is:"1" %} |
112 |
117 |
<dt>{% translate "Modified file" %}</dt> |
113 |
118 |
{% else %} |
114 |
119 |
<dt>{% translate "Modified files" %}</dt> |
115 |
120 |
{% endif %} |
116 |
121 |
{% for mod_file in modified_files %} |
117 |
122 |
<dd><a href="#{{ mod_file.path }}">{{ mod_file.path }}</a></dd> |
118 |
123 |
{% endfor %} |
119 |
124 |
{#<dt>{% translate "Child" %}</dt>#} |
120 |
125 |
{# <dd>{{ commit.author_date|date:"DATETIME_FORMAT" }}</dd>#} |
121 |
126 |
{# Gonna leave the email out for now, don't like email scrapers #} |
122 |
127 |
{# <dt>{% translate "E-mail" %}</dt> #} |
123 |
128 |
{# <dl>{{ commit.author.email }}</dl> #} |
124 |
129 |
</dl> |
125 |
130 |
</section> |
126 |
131 |
|
127 |
132 |
{% for mod_file in modified_files %} |
128 |
133 |
<section> |
129 |
134 |
<h3 id="{{ mod_file.path }}">{{ mod_file.path }} <a href="#{{ mod_file.path }}">¶</a></h3> |
130 |
135 |
<p> |
131 |
136 |
{{ mod_file.object.added_lines }} |
132 |
137 |
{% blocktranslate count counter=mod_file.object.added_lines %} |
133 |
138 |
addition |
134 |
139 |
{% plural %} |
135 |
140 |
additions |
136 |
141 |
{% endblocktranslate %} |
137 |
142 |
{% translate "and" %} |
138 |
143 |
{{ mod_file.object.deleted_lines }} |
139 |
144 |
{% blocktranslate count counter=mod_file.object.deleted_lines %} |
140 |
145 |
deletion. |
141 |
146 |
{% plural %} |
142 |
147 |
deletions. |
143 |
148 |
{% endblocktranslate %} |
144 |
149 |
</p> |
145 |
150 |
{% if mod_file.methods_available %} |
146 |
151 |
|
147 |
152 |
{% endif %} |
148 |
153 |
<details open> |
149 |
154 |
<summary class="ripple"><span class="closed"> {% translate "View changes" %}</span><span class="opened"> {% translate "Hide changes" %}</span> |
150 |
155 |
</summary> |
151 |
156 |
|
152 |
157 |
<table class="highlight" style="font-family: 'Fira Code', monospace;"> |
153 |
158 |
{% for row in mod_file.rows %} |
154 |
159 |
{% if row.type == "deletion" %} |
155 |
160 |
<tr class="deletion"> |
156 |
161 |
<td id="{{ mod_file.path }}-A{{ row.old_num }}" class="line-number"> |
157 |
162 |
<a href="#{{ mod_file.path }}-A{{ row.old_num }}" class="accent-on-hover-only"><pre>{{ row.old_num }}</pre> |
158 |
163 |
</a></td> |
159 |
164 |
<td class="line-number symbol">-</td> |
160 |
165 |
{% elif row.type == "addition" %} |
161 |
166 |
<tr class="addition"> |
162 |
167 |
<td class="line-number symbol">+</td> |
163 |
168 |
<td id="{{ mod_file.path }}-B{{ row.new_num }}" class="line-number"> |
164 |
169 |
<a href="#{{ mod_file.path }}-B{{ row.new_num }}" class="accent-on-hover-only"><pre>{{ row.new_num }}</pre> |
165 |
170 |
</a></td> |
166 |
171 |
{% else %} |
167 |
172 |
<tr class="nochange"> |
168 |
173 |
<td id="{{ mod_file.path }}-A{{ row.old_num }}" class="line-number"> |
169 |
174 |
<a href="#{{ mod_file.path }}-A{{ row.old_num }}" class="accent-on-hover-only"><pre>{{ row.old_num }}</pre> |
170 |
175 |
<td id="{{ mod_file.path }}-B{{ row.new_num }}" class="line-number"> |
171 |
176 |
<a href="#{{ mod_file.path }}-B{{ row.new_num }}" class="accent-on-hover-only"><pre>{{ row.new_num }}</pre> |
172 |
177 |
</a></td> |
173 |
178 |
{% endif %} |
174 |
179 |
<td style="padding-left: 1em;"><pre>{{ row.line|safe }}</pre></td> |
175 |
180 |
</tr> |
176 |
181 |
{% endfor %} |
177 |
182 |
</table> |
178 |
183 |
</details> |
179 |
184 |
</section> |
180 |
185 |
{% endfor %} |
181 |
186 |
|
182 |
187 |
{% endblock main %} |
183 |
188 |
templates/gitar/directory.djhtml ¶
3 additions and 0 deletions.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
{% load humanize %} |
3 |
3 |
{% load static %} |
4 |
4 |
|
5 |
5 |
{% block title %}{{ repository_name }} | Gitar{% endblock title %} |
6 |
6 |
|
7 |
7 |
{% block stylesheets %} |
8 |
8 |
{{ block.super }} |
9 |
9 |
<style> |
10 |
10 |
td { |
+ |
11 |
display: table; |
+ |
12 |
} |
+ |
13 |
td { |
11 |
14 |
padding-right: 1em; |
12 |
15 |
} |
13 |
16 |
</style> |
14 |
17 |
{% endblock stylesheets %} |
15 |
18 |
|
16 |
19 |
{% block description %} |
17 |
20 |
{{repository_description}} |
18 |
21 |
{% endblock description %} |
19 |
22 |
|
20 |
23 |
{% block header %} |
21 |
24 |
<header> |
22 |
25 |
<label for="nav-drawer-toggle">≡</label> |
23 |
26 |
<h1>{{ repository_name }}</h1> |
24 |
27 |
</header> |
25 |
28 |
{% endblock header %} |
26 |
29 |
|
27 |
30 |
{% block nav %} |
28 |
31 |
<input id="nav-drawer-toggle" type="checkbox" /> |
29 |
32 |
<nav> |
30 |
33 |
<label for="nav-drawer-toggle">🡠</label> |
31 |
34 |
<h2>{{ repository_name }}</h2> |
32 |
35 |
<a class="nav-link" href="{% url 'gitar-index' %}">Gitar | Index</a> |
33 |
36 |
<a class="nav-link" href="{% url 'about-index' %}">{% translate "Front page" %}</a> |
34 |
37 |
{% if subdirectories %} |
35 |
38 |
<hr class="half"> |
36 |
39 |
{% endif %} |
37 |
40 |
{% for subdirectory in subdirectories %} |
38 |
41 |
<a class="nav-link" href="{% url 'gitar-path-explorer' repository_name branch subdirectory.path %}"> |
39 |
42 |
{{ subdirectory.name }} |
40 |
43 |
</a> |
41 |
44 |
{% endfor %} |
42 |
45 |
<hr class="half"> |
43 |
46 |
{% for file in files %} |
44 |
47 |
<a class="nav-link" href="{% url 'gitar-path-explorer' repository_name branch file.path %}"> |
45 |
48 |
{{ file.name }} |
46 |
49 |
</a> |
47 |
50 |
{% endfor %} |
48 |
51 |
</nav> |
49 |
52 |
{% endblock nav %} |
50 |
53 |
|
51 |
54 |
{% block main %} |
52 |
55 |
<aside> |
53 |
56 |
<!-- Add tertiary information such as branches and licensing here. --> |
54 |
57 |
<h2>{{repository_name}}</h2> |
55 |
58 |
<p>{{ repository_description }}</p> |
56 |
59 |
<h3>{% trans "Branches" %}</h3> |
57 |
60 |
{% for bbranch in branches %} |
58 |
61 |
<a href="{% url 'gitar-repository' repository_name bbranch %}"> |
59 |
62 |
{{ bbranch }} |
60 |
63 |
</a><br> |
61 |
64 |
{% endfor %} |
62 |
65 |
{% comment %}<h5 class="{{mdc}}-text">{% trans "Extra information" %}</h5> |
63 |
66 |
<div class="chip"> |
64 |
67 |
{{repository_language}} |
65 |
68 |
<i class="material-icons {{mdac}}-text text-accent-3">code</i> |
66 |
69 |
</div><br /> |
67 |
70 |
<div class="chip"> |
68 |
71 |
{{repository_license}} |
69 |
72 |
<i class="material-icons {{mdac}}-text text-accent-3">copyright</i> |
70 |
73 |
</div> |
71 |
74 |
{% endcomment %} |
72 |
75 |
</aside> |
73 |
76 |
<section> |
74 |
77 |
<h2>{% translate "Content" %}</h2> |
75 |
78 |
<!--Tree contents--> |
76 |
79 |
<!-- Subdirectories --> |
77 |
80 |
{% if subdirectories %} |
78 |
81 |
<table> |
79 |
82 |
<thead> |
80 |
83 |
<tr> |
81 |
84 |
<th scope="col">{% translate "Subdirectories" %}</th> |
82 |
85 |
</tr> |
83 |
86 |
</thead> |
84 |
87 |
<tbody> |
85 |
88 |
{% for subdirectory in subdirectories %} |
86 |
89 |
<tr> |
87 |
90 |
<th> |
88 |
91 |
<a href="{% url 'gitar-path-explorer' repository_name branch subdirectory.path %}"> |
89 |
92 |
{{subdirectory.name}} |
90 |
93 |
</a> |
91 |
94 |
</th> |
92 |
95 |
</tr> |
93 |
96 |
{% endfor %} |
94 |
97 |
</tbody> |
95 |
98 |
</table> |
96 |
99 |
{% endif %} |
97 |
100 |
<!-- Files --> |
98 |
101 |
<table> |
99 |
102 |
<thead> |
100 |
103 |
<tr> |
101 |
104 |
<th scope="col">{% translate "File name" %}</th> |
102 |
105 |
<th scope="col">{% translate "Latest commit" %}</th> |
103 |
106 |
<th scope="col">{% translate "Latest update" %}</th> |
104 |
107 |
</tr> |
105 |
108 |
</thead> |
106 |
109 |
<tbody> |
107 |
110 |
{% for file in files %} |
108 |
111 |
<tr> |
109 |
112 |
<td><a href="{% url 'gitar-path-explorer' repository_name branch file.path %}"> |
110 |
113 |
{{ file.name }}</a></td> |
111 |
114 |
<td><a href="{% url 'gitar-commit' repository_name file.commit.hash %}"> |
112 |
115 |
{{ file.commit.msg|truncatewords_html:10 }}</a></td> |
113 |
116 |
<td>{% if file.older_than_one_month %} |
114 |
117 |
{{ file.commit.committer_date|date }} |
115 |
118 |
{% else %} |
116 |
119 |
{{ file.commit.committer_date|naturaltime }} |
117 |
120 |
{% endif %} |
118 |
121 |
</td> |
119 |
122 |
</tr> |
120 |
123 |
{% endfor %} |
121 |
124 |
</tbody> |
122 |
125 |
</table> |
123 |
126 |
<!-- Commits --> |
124 |
127 |
<h2>{% translate "Commits" %}</h2> |
125 |
128 |
<table> |
126 |
129 |
<thead> |
127 |
130 |
<tr> |
128 |
131 |
<th scope="col">{% translate "Hash" %}</th> |
129 |
132 |
<th scope="col">{% translate "Author" %}</th> |
130 |
133 |
<th scope="col">{% translate "Description" %}</th> |
131 |
134 |
<th scope="col">{% translate "Date" %}</th> |
132 |
135 |
</tr> |
133 |
136 |
</thead> |
134 |
137 |
<tbody> |
135 |
138 |
{% for commit in commits %} |
136 |
139 |
<tr> |
137 |
140 |
<td><a href="{% url 'gitar-commit' repository_name commit.hash %}"> |
138 |
141 |
<code>{{ commit.hash|truncatechars:15 }}</code> |
139 |
142 |
</a></td> |
140 |
143 |
<td>{{ commit.author|truncatewords:2 }}</td> |
141 |
144 |
<td> |
142 |
145 |
{{ commit.description|lower|capfirst|truncatewords:10|truncatechars:80 }}{% if commit.description|last != "." %}.{% endif %} |
143 |
146 |
</td> |
144 |
147 |
<td>{{ commit.date|date:"SHORT_DATETIME_FORMAT" }}</td> |
145 |
148 |
{% endfor %} |
146 |
149 |
</tbody> |
147 |
150 |
</table> |
148 |
151 |
</section> |
149 |
152 |
{% endblock main %} |
150 |
153 |