Skip to content
This repository was archived by the owner on Jun 14, 2023. It is now read-only.

Commit 8893ceb

Browse files
author
Thomas Bourrely
committed
feat: subguides tree
1 parent b30afbf commit 8893ceb

File tree

8 files changed

+237
-25
lines changed

8 files changed

+237
-25
lines changed

Diff for: plugins/ovh_entities/ovh_entities.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def handle_entity_generator_finalized(generator):
6464
items = [entity]
6565
items += entity.translations
6666
parent = [e for e in generator.entities if e.dir == entity.parent_dir and entity.type in e.settings['CHILDREN']]
67-
67+
6868
if len(parent) == 0 and not entity.settings['IS_ROOT']:
6969
logger.warning("No parent found for file %s", entity.source_path)
7070

@@ -131,7 +131,7 @@ def parents(self):
131131
parents_found = [t for t in e.parent.translations if t.getLang() == lang]
132132
if len(parents_found) > 0:
133133
e.parent = parents_found[0]
134-
134+
135135
self._parents.insert(0, e.parent)
136136
e = e.parent
137137

@@ -161,7 +161,7 @@ def override_url(self):
161161
self._override_url = generated_url
162162

163163
return self._override_url
164-
164+
165165
@property
166166
def override_save_as(self):
167167
return self.override_url + 'index.html'
@@ -197,7 +197,7 @@ def replacer(m):
197197
value = m.group('value')
198198
path = m.group('path')
199199
title = m.group('text')
200-
200+
201201
if what == 'legacy' and hasattr(self, 'lang'):
202202
key = '{}-{}'.format(self.lang, value)
203203
if key in self._context['uids']:
@@ -208,7 +208,7 @@ def replacer(m):
208208
value = '#legacy:' + value
209209
elif what == 'ovh_www' and hasattr(self, 'lang'):
210210
value = self.appendOvhHost(value)
211-
211+
212212
return '<a href="{}">{}<'.format(value, title)
213213

214214
return hrefs.sub(replacer, content)
@@ -219,7 +219,7 @@ def getLang(self):
219219
def appendOvhHost(self, value):
220220
if not value:
221221
return ''
222-
222+
223223
if (value[0] != '/'):
224224
value = '/' + value
225225

@@ -251,7 +251,7 @@ def get_files(self, paths, exclude=[], extensions=None):
251251
files.append(filepath)
252252

253253
return files
254-
254+
255255
def generate_context(self):
256256
"""Add the entities into the shared context"""
257257

@@ -319,4 +319,4 @@ def generate_context(self):
319319
self.readers.save_cache()
320320

321321
def __init__(self, *args, **kwargs):
322-
super(OvhEntityGenerator, self).__init__(*args, **kwargs)
322+
super(OvhEntityGenerator, self).__init__(*args, **kwargs)

Diff for: plugins/ovh_filters/ovh_filters.py

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .related import related
1010
from .visible import visible
1111
from .doorbell import doorbell
12+
from .tree import tree
1213

1314
def add_filter(generator):
1415
translator = Translator(generator.settings)
@@ -19,6 +20,7 @@ def add_filter(generator):
1920
generator.env.filters.update({'related': related})
2021
generator.env.filters.update({'visible': visible})
2122
generator.env.filters.update({'doorbell': doorbell})
23+
generator.env.filters.update({'tree': tree})
2224

2325
def register():
2426
"""Plugin registration."""

Diff for: plugins/ovh_filters/tests/test_tree.py

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import unittest
2+
from jinja2 import Environment, BaseLoader
3+
from entities import Entity
4+
5+
import sys
6+
sys.path.append('../..')
7+
from ovh_filters.tree import tree
8+
9+
10+
class CustomEntity(Entity):
11+
@property
12+
def url(self):
13+
return self.custom_url
14+
15+
16+
class TestTree(unittest.TestCase):
17+
18+
def mockEntity(self, title, children=None, url=None, parent=None, type=None):
19+
entity = CustomEntity(content=None)
20+
entity.title = title
21+
entity.children = children
22+
entity.custom_url = url
23+
entity.parent = parent
24+
entity.type = type
25+
return entity
26+
27+
def test_tree_entity_with_children(self):
28+
baseEntity = self.mockEntity('Parent')
29+
30+
child1 = self.mockEntity('Child1', url='/a/test')
31+
child2 = self.mockEntity('Child2', url='/b/test2')
32+
33+
baseEntity.children = [
34+
child1,
35+
child2
36+
]
37+
38+
result = tree(baseEntity)
39+
expected = {
40+
'title': baseEntity.title,
41+
'url': baseEntity.url,
42+
'active': True,
43+
'children': [
44+
{
45+
'title': child1.title,
46+
'active': False,
47+
'url': child1.url,
48+
},
49+
{
50+
'title': child2.title,
51+
'active': False,
52+
'url': child2.url,
53+
},
54+
]
55+
}
56+
57+
self.assertEqual(result, expected)
58+
59+
def test_tree_child_guide(self):
60+
baseEntity = self.mockEntity(title="Parent", type="Guide")
61+
child1 = self.mockEntity(title="Child1", type="Guide", parent=baseEntity)
62+
child2 = self.mockEntity(title="Child2", type="Guide", parent=baseEntity)
63+
baseEntity.children = [
64+
child1,
65+
child2
66+
]
67+
68+
result = tree(child1)
69+
expected = {
70+
'title': baseEntity.title,
71+
'active': False,
72+
'url': baseEntity.url,
73+
'children': [
74+
{
75+
'title': child1.title,
76+
'active': True,
77+
'url': child1.url,
78+
},
79+
{
80+
'title': child2.title,
81+
'active': False,
82+
'url': child2.url,
83+
},
84+
]
85+
}
86+
87+
self.assertEqual(result, expected)
88+
89+
def test_tree_entity_with_children_2_levels_deep(self):
90+
baseEntity = self.mockEntity(title="Parent", type="Guide")
91+
child1 = self.mockEntity(title="Child1", type="Guide", parent=baseEntity)
92+
child2 = self.mockEntity(title="Child2", type="Guide", parent=child1)
93+
child3 = self.mockEntity(title="Child3", type="Guide", parent=child2)
94+
child4 = self.mockEntity(title="Child4", type="Guide", parent=child1)
95+
96+
child2.children = [ child3 ]
97+
child1.children = [ child2, child4 ]
98+
baseEntity.children = [ child1 ]
99+
100+
result = tree(child3)
101+
expected = {
102+
'title': baseEntity.title,
103+
'url': baseEntity.url,
104+
'active': False,
105+
'children': [
106+
{
107+
'title': child1.title,
108+
'active': False,
109+
'url': child1.url,
110+
'children': [
111+
{
112+
'title': child2.title,
113+
'url': child2.url,
114+
'active': False,
115+
'children': [
116+
{
117+
'title': child3.title,
118+
'active': True,
119+
'url': child3.url,
120+
}
121+
]
122+
},
123+
{
124+
'title': child4.title,
125+
'active': False,
126+
'url': child4.url,
127+
},
128+
]
129+
},
130+
]
131+
}
132+
133+
self.assertEqual(result, expected)
134+

Diff for: plugins/ovh_filters/tree.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
def tree(entity):
2+
"""tree is a filter to build the file tree
3+
4+
Args:
5+
entity: the current entity
6+
7+
Returns:
8+
A file tree, starting with the highest parent
9+
"""
10+
root = entity
11+
12+
# Get the highest available parent
13+
while hasattr(root, 'parent') and root.parent and root.parent.type == root.type:
14+
root = root.parent
15+
16+
# Use it to build the file tree
17+
return build_tree(root, entity.title)
18+
19+
def build_tree(node, active_title=None):
20+
items = []
21+
22+
if not hasattr(node, 'children') or not node.children:
23+
return {
24+
'title': node.title,
25+
'url': node.url,
26+
'active': True if node.title == active_title else False
27+
}
28+
29+
for child in node.children:
30+
items.append(build_tree(child, active_title))
31+
32+
return {
33+
'title': node.title,
34+
'url': node.url,
35+
'children': items,
36+
'active': True if node.title == active_title else False
37+
}
38+

Diff for: themes/ovh/static/css/components/subguides.css

+37-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
11
.subguides {
2-
margin: 1.5rem 30px;
2+
margin: 1.5rem 30px;
33
}
44

55
.subguides::before {
6-
content: '';
7-
display: block;
8-
width: 100%;
9-
height: 1px;
10-
background-color: #d3d3d3;
11-
margin-bottom: 1.5rem;
6+
content: '';
7+
display: block;
8+
width: 100%;
9+
height: 1px;
10+
background-color: #d3d3d3;
11+
margin-bottom: 1.5rem;
1212
}
1313

1414
#sidebar-nav a.subguides__link {
15-
font-weight: normal;
16-
padding-left: 0;
15+
font-weight: normal;
16+
padding-left: 0;
1717
}
18+
19+
.subguides__parent {
20+
font-weight: bold;
21+
}
22+
23+
#sidebar-nav a.subguides__parent {
24+
padding: 0;
25+
margin: 0 0 1rem 0;
26+
}
27+
28+
.subguides__list__element {
29+
position: relative;
30+
padding-left: 1rem;
31+
}
32+
33+
#sidebar-nav .subguides__list__element--active > a.subguides__link {
34+
font-weight: bold;
35+
font-style: italic;
36+
}
37+
38+
.subguides__list__element::before {
39+
position: absolute;
40+
left: 0;
41+
font-family: 'Font Awesome 5 Free';
42+
font-weight: 900;
43+
content: '\f0da'
44+
}
45+

Diff for: themes/ovh/static/css/sidebar.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#sidebar-nav.affix { position: fixed; top: 64px; width: 265px; }
1+
#sidebar-nav.affix { position: fixed; top: 64px; width: 233px; }
22
#sidebar-nav ul { list-style: none; margin: 0; padding: 0; display: block; }
33
#sidebar-nav ul ul { font-size: 0.8rem; border-bottom: none; margin-left: 14px;}
44
#sidebar-nav ul ul ul{display: none;}
+16-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
{% set items = entity|tree %}
2+
3+
{% if items.children %}
14
<div class="subguides">
5+
<a class="subguides__parent" href="/{{ items.url }}">{{ items.title }}</a>
26
<ul class="subguides__list">
3-
{% for child in entity.children %}
4-
<li class="subguides__list__element">
5-
<a class="subguides__link" href="/{{ child.url }}">{{ child.title }}</a>
6-
</li>
7+
{% for item in items.children recursive %}
8+
<li class="subguides__list__element
9+
{% if item.active %}subguides__list__element--active{% endif %}">
10+
<a class="subguides__link" href="/{{ item.url }}">{{ item.title }}</a>
11+
</li>
12+
13+
{% if item.children %}
14+
<ul class="subguides__list">
15+
{{ loop(item.children) }}
16+
</ul>
17+
{% endif %}
718
{% endfor %}
819
</ul>
920
</div>
21+
{% endif %}

Diff for: themes/ovh/templates/guide.html

+1-3
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@
120120
{{entity.toc.replace('<div id="toc"><ul>', '<div id="toc"><ul class="nav">')}}
121121
{% endif %}
122122

123-
{% if entity.children %}
124-
{% include 'components/subguides/subguides.html' %}
125-
{% endif %}
123+
{% include 'components/subguides/subguides.html' %}
126124
</nav>
127125
</div>
128126
{% endif %}

0 commit comments

Comments
 (0)