Add the navbar

This commit is contained in:
Rodolphe Breard 2018-01-21 13:44:00 +01:00
parent c9c8228e22
commit 89a10d3b6a
42 changed files with 281 additions and 1 deletions

View file

@ -40,6 +40,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'khaganat',
'pages.apps.PagesConfig',
'navbar.apps.NavbarConfig',
]
MIDDLEWARE = [

View file

@ -4,6 +4,22 @@ html,body {
color: #222;
}
#mainNav {
padding-top: 0;
padding-bottom: 0;
background-color: #efeded;
opacity: 0.8;
}
.tooltip-inner {
background-color: #efeded;
color: #222;
}
.tooltip.bs-tooltip-auto[x-placement^=right] .arrow::before, .tooltip.bs-tooltip-right .arrow::before {
border-right-color: #efeded;
}
.content-bloc {
margin: 10px;
padding: 10px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

4
khaganat/static/jquery-3.2.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})

View file

@ -1,4 +1,4 @@
{% load static %}<!doctype html>
{% load static %}{% load navbar %}<!doctype html>
<html lang="en">
<head>
<!-- Begin bootstrap headers -->
@ -19,8 +19,12 @@
<title>Khaganat - {% block title %}{% endblock %}</title>
</head>
<body>
{% navbar %}
<div class="container" id="main-content">
{% block content %}{% endblock %}
</div>
<script src="{% static "jquery-3.2.1.min.js" %}"></script>
<script src="{% static "bootstrap/4.0.0-beta.3/js/bootstrap.bundle.min.js" %}"></script>
<script src="{% static "js/khaganat.js" %}"></script>
</body>
</html>

0
navbar/__init__.py Normal file
View file

11
navbar/admin.py Normal file
View file

@ -0,0 +1,11 @@
from django.contrib import admin
from .models import Element,ElementDescription
class ElementDescriptionInline(admin.StackedInline):
model = ElementDescription
extra = 2
class ElementAdmin(admin.ModelAdmin):
inlines = [ElementDescriptionInline]
admin.site.register(Element, ElementAdmin)

5
navbar/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class NavbarConfig(AppConfig):
name = 'navbar'

View file

@ -0,0 +1,28 @@
# Generated by Django 2.0.1 on 2018-01-20 15:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Element',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('link', models.CharField(blank=True, max_length=512)),
('new_window', models.BooleanField(default=False)),
('icon', models.FilePathField(match='*.png', path='/home/rodolphe/projects/khaganat-web/navbar/static/icons')),
('short_name', models.CharField(max_length=32)),
('full_name', models.CharField(max_length=64)),
('description', models.CharField(max_length=512)),
('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='navbar.Element')),
],
),
]

View file

@ -0,0 +1,34 @@
# Generated by Django 2.0.1 on 2018-01-20 15:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('navbar', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='element',
name='description',
field=models.CharField(blank=True, max_length=512),
),
migrations.AlterField(
model_name='element',
name='full_name',
field=models.CharField(blank=True, max_length=64),
),
migrations.AlterField(
model_name='element',
name='icon',
field=models.FilePathField(blank=True, match='.png', null=True, path='/home/rodolphe/projects/khaganat-web/navbar/static/icons'),
),
migrations.AlterField(
model_name='element',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='navbar.Element'),
),
]

View file

@ -0,0 +1,41 @@
# Generated by Django 2.0.1 on 2018-01-20 15:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('navbar', '0002_auto_20180120_1637'),
]
operations = [
migrations.CreateModel(
name='ElementDescription',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(choices=[('en', 'English'), ('fr', 'French')], max_length=10)),
('short_name', models.CharField(max_length=32)),
('full_name', models.CharField(blank=True, max_length=64)),
('description', models.CharField(blank=True, max_length=512)),
],
),
migrations.RemoveField(
model_name='element',
name='description',
),
migrations.RemoveField(
model_name='element',
name='full_name',
),
migrations.RemoveField(
model_name='element',
name='short_name',
),
migrations.AddField(
model_name='elementdescription',
name='element',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='navbar.Element'),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 2.0.1 on 2018-01-20 16:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('navbar', '0003_auto_20180120_1644'),
]
operations = [
migrations.AddField(
model_name='element',
name='weight',
field=models.PositiveSmallIntegerField(default=0),
preserve_default=False,
),
]

View file

31
navbar/models.py Normal file
View file

@ -0,0 +1,31 @@
from django.utils.translation import get_language
from django.conf import settings
from django.db import models
import os
class Element(models.Model):
parent = models.ForeignKey('Element', on_delete=models.CASCADE, null=True, blank=True)
link = models.CharField(max_length=512, blank=True)
new_window = models.BooleanField(default=False)
icon = models.FilePathField(path=os.path.join(settings.BASE_DIR, 'navbar/static/icons'), match=".png", null=True, blank=True)
weight = models.PositiveSmallIntegerField()
def icon_path(self):
return os.path.join('icons', os.path.basename(self.icon))
def children(self):
return Element.objects.filter(parent=self.id).order_by('weight')
def description(self):
return ElementDescription.objects.filter(element=self.id, language=get_language()).first()
def __str__(self):
desc = self.description()
return desc.short_name if desc is not None else self.link
class ElementDescription(models.Model):
element = models.ForeignKey(Element, on_delete=models.CASCADE)
language = models.CharField(max_length=10, choices=settings.LANGUAGES)
short_name = models.CharField(max_length=32)
full_name = models.CharField(max_length=64, blank=True)
description = models.CharField(max_length=512, blank=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

BIN
navbar/static/icons/ds.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

BIN
navbar/static/icons/irc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

BIN
navbar/static/icons/mag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
navbar/static/icons/pad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

BIN
navbar/static/icons/um1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

View file

@ -0,0 +1,43 @@
{% load static %}<nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
<a class="navbar-brand" href="/{{ current_lang_code }}/">
<img src="{% static "images/icon_khaganat.png" %}" alt="Khaganat">
</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{% for e in elems %}
{% if e.link %}
<li class="nav-item">
<a class="nav-link" href="{{ e.link }}"{% if e.new_window %} target="_blank"{% endif %}>{{ e }}</a>
</li>
{% elif e.children %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ e.description.short_name }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
{% for c in e.children %}
<a class="dropdown-item" href="{{ c.link }}"{% if c.new_window %} target="_blank"{% endif %}{% if c.description.full_name or c.description.description %} data-toggle="tooltip" data-placement="right" data-html="true" title="{% if c.description.full_name %}<b>{{ c.description.full_name }}</b>{% endif %}{% if c.description.full_name and c.description.description %}<hr />{% endif %}{{ c.description.description }}"{% endif %}>
<img src="{% static c.icon_path %}" alt="" /> {{ c }}
</a>
{% endfor %}
</div>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link disabled" href="#">{{ e }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item dropdown">
<a class="nav-item nav-link dropdown-toggle mr-md-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ current_lang_name }}</a>
<div class="dropdown-menu dropdown-menu-right">
{% for lang_code, lang_name in all_langs %}
<a class="dropdown-item{% if lang_code == current_lang_code %} active{% endif %}" href="/{{ lang_code }}/{{ current_url }}">{{ lang_name }}</a>
{% endfor %}
</div>
</li>
</ul>
</nav>

View file

View file

@ -0,0 +1,34 @@
from django.utils.translation import get_language,gettext_lazy as _,activate as activate_lang
from django.template.response import TemplateResponse
from django.utils.safestring import mark_safe
from django.shortcuts import render
from navbar.models import Element
from django.conf import settings
from django import template
import re
register = template.Library()
path_re = re.compile('^(/[a-z]+)/(.*)')
def get_lang_name(lang_code):
activate_lang(lang_code)
return str([e for e in settings.LANGUAGES if e[0] == lang_code].pop()[1])
def reduce_path(path):
m = path_re.match(path)
return m.group(2) if m else path
@register.simple_tag(takes_context=True)
def navbar(context):
request = context['request']
curr_lang = get_language()
ctx = {
'elems': Element.objects.filter(parent=None).order_by('weight'),
'current_url': reduce_path(request.path_info),
'current_lang_code': curr_lang,
'current_lang_name': get_lang_name(curr_lang),
'all_langs': [(l[0], get_lang_name(l[0])) for l in settings.LANGUAGES],
}
activate_lang(curr_lang)
tpl = TemplateResponse(request, 'navbar/navbar.html', context=ctx).render()
return mark_safe(tpl.rendered_content)

3
navbar/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
navbar/views.py Normal file
View file

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.