- {{ paragraph|safe }}
+ {% if shortcuts %}
+
+
+
+ {% for shortcut in shortcuts %}
+ {% if not shortcut.hidden %}
+ {% if user.is_authenticated or not shortcut.login_required %}
+
+ {% endif %}
+ {% endif %}
+ {% endfor %}
- {% endfor %}
-
-
- {% if user.is_authenticated and user_is_admin and configure_url %}
-
- {% trans "Configure »" %}
- {% endif %}
-
+
{% endif %}
diff --git a/plinth/templates/system.html b/plinth/templates/system.html
index 44c4a8374..e0dcbdb61 100644
--- a/plinth/templates/system.html
+++ b/plinth/templates/system.html
@@ -1,4 +1,4 @@
-{% extends 'base.html' %}
+{% extends 'cards.html' %}
{% comment %}
#
# This file is part of FreedomBox.
@@ -18,30 +18,13 @@
#
{% endcomment %}
+{% load static %}
{% load i18n %}
-{% block submenu %}
- {% if submenu %}
-
- {% endif %}
-{% endblock %}
-
-{% block content %}
-
-
{% trans "System Configuration" %}
-
-
- {% blocktrans trimmed %}
- Here you can administrate the underlying system of your {{ box_name }}.
- {% endblocktrans %}
-
-
-
- {% blocktrans trimmed %}
- The options affect the {{ box_name }} at its most general level,
- so be careful!
- {% endblocktrans %}
-
+{% block page_head %}
+
{% endblock %}
diff --git a/plinth/tests/test_menu.py b/plinth/tests/test_menu.py
index c21013fa9..7fb1a0dc6 100644
--- a/plinth/tests/test_menu.py
+++ b/plinth/tests/test_menu.py
@@ -38,14 +38,16 @@ def build_menu(size=5):
random.seed()
item_data = []
for index in range(1, size + 1):
- item_data.append(['Item' + str(index),
+ item_data.append(['Name' + str(index),
+ 'ShortDescription' + str(index),
+ 'Item' + str(index),
'Icon' + str(index),
URL_TEMPLATE.format(index, index, index),
random.randint(0, 1000)])
menu = Menu()
for data in item_data:
- menu.add_item(data[0], data[1], data[2], data[3])
+ menu.add_item(data[0], data[1], data[2], data[3], data[4], data[5])
return menu
@@ -90,13 +92,17 @@ class MenuTestCase(TestCase):
def test_menu_creation_with_arguments(self):
"""Verify the Menu state with initialization parameters."""
+ expected_name = 'Name'
+ expected_short_description = 'ShortDescription'
expected_label = 'Label'
expected_icon = 'Icon'
expected_url = '/aaa/bbb/ccc/'
expected_order = 42
- menu = Menu(expected_label, expected_icon, expected_url,
+ menu = Menu(expected_name, expected_short_description, expected_label, expected_icon, expected_url,
expected_order)
+ self.assertEqual(expected_name, menu.name)
+ self.assertEqual(expected_short_description, menu.short_description)
self.assertEqual(expected_label, menu.label)
self.assertEqual(expected_icon, menu.icon)
self.assertEqual(expected_url, menu.url)
@@ -105,17 +111,21 @@ class MenuTestCase(TestCase):
def test_get(self):
"""Verify that a menu item can be correctly retrieved."""
+ expected_name = 'Name2'
+ expected_short_description = 'ShortDescription2'
expected_label = 'Label2'
expected_icon = 'Icon2'
expected_url = 'index'
reversed_url = reverse(expected_url)
expected_order = 2
menu = Menu()
- menu.add_item(expected_label, expected_icon, reversed_url,
+ menu.add_item(expected_name, expected_short_description, expected_label, expected_icon, reversed_url,
expected_order)
actual_item = menu.get(expected_url)
self.assertIsNotNone(actual_item)
+ self.assertEqual(expected_name, actual_item.name)
+ self.assertEqual(expected_short_description, actual_item.short_description)
self.assertEqual(expected_label, actual_item.label)
self.assertEqual(expected_icon, actual_item.icon)
self.assertEqual(reversed_url, actual_item.url)
@@ -124,12 +134,14 @@ class MenuTestCase(TestCase):
def test_get_with_item_not_found(self):
"""Verify that a KeyError is raised if a menu item is not found."""
+ expected_name = 'Name3'
+ expected_short_description = 'ShortDescription3'
expected_label = 'Label3'
expected_icon = 'Icon3'
expected_url = 'index'
expected_order = 3
menu = Menu()
- menu.add_item(expected_label, expected_icon, expected_url,
+ menu.add_item(expected_name, expected_short_description, expected_label, expected_icon, expected_url,
expected_order)
self.assertRaises(KeyError, menu.get, expected_url)
@@ -175,17 +187,21 @@ class MenuTestCase(TestCase):
def test_add_item(self):
"""Verify that a menu item can be correctly added."""
+ expected_name = 'Name5'
+ expected_short_description = 'ShortDescription5'
expected_label = 'Label5'
expected_icon = 'Icon5'
expected_url = '/jjj/kkk/lll/'
expected_order = 5
menu = Menu()
- actual_item = menu.add_item(expected_label, expected_icon,
+ actual_item = menu.add_item(expected_name, expected_short_description, expected_label, expected_icon,
expected_url, expected_order)
self.assertEqual(1, len(menu.items))
self.assertIsNotNone(actual_item)
self.assertEqual(actual_item, menu.items[0])
+ self.assertEqual(expected_name, actual_item.name)
+ self.assertEqual(expected_short_description, actual_item.short_description)
self.assertEqual(expected_label, actual_item.label)
self.assertEqual(expected_icon, actual_item.icon)
self.assertEqual(expected_url, actual_item.url)
diff --git a/static/themes/default/css/plinth.css b/static/themes/default/css/plinth.css
index 1518400de..2f33d2d93 100644
--- a/static/themes/default/css/plinth.css
+++ b/static/themes/default/css/plinth.css
@@ -4,10 +4,12 @@
}
body {
- padding-top: 70px;
+ padding-top: 6em;
position: relative;
font-family: LatoRegular, sans-serif;
font-size: 15px;
+ background-repeat: no-repeat;
+ background-position: 22.5px 75px;
}
.multiple-checkbox li {
@@ -21,7 +23,7 @@ body {
.navbar-brand img {
float: left;
- margin-top: -14px;
+ margin-top: -10px;
padding: 8px;
}
@@ -63,6 +65,10 @@ body {
animation: spin 1s linear infinite;
}
+.nav-link:hover, .nav-link:visited, .nav-link:link, .nav-link:active {
+ text-decoration: none;
+}
+
@keyframes spin {
0% {
transform: rotate(0deg);
@@ -178,3 +184,99 @@ footer license-info p {
.manual-page {
text-align: right;
}
+
+/* applying styles to header - begin */
+.main-header {
+ background: #4989D4;
+ box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.25);
+ border: none;
+}
+
+.main-header .navbar-nav>li>a {
+ color: #FFF;
+}
+
+.main-header.navbar-default .navbar-nav>li>a:focus,
+.main-header.navbar-default .navbar-nav>li>a:hover,
+.main-header.navbar-default .navbar-nav>.active>a,
+.main-header.navbar-default .navbar-nav>.active>a:hover,
+.main-header.navbar-default .navbar-nav>.active>a:focus,
+.main-header.navbar-default .navbar-nav>.open>a,
+.main-header.navbar-default .navbar-nav>.open>a:hover,
+.main-header.navbar-default .navbar-nav>.open>a:focus {
+ color: #FFF;
+ background: transparent;
+}
+
+.main-header .navbar-nav>li>a .nav-icon {
+ margin-right: 0px;
+}
+/* applying styles to header - end */
+
+.card-list {
+ width: 100%;
+ max-width: 1500px;
+ margin: 0 auto;
+ padding: 0 10px;
+
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+a.menu_link {
+ text-decoration: none;
+}
+
+a.menu_link:hover,a.menu_link:active {
+ text-decoration: none;
+}
+
+a.menu_link_active {
+ border-bottom: white 3px solid;
+}
+
+.card {
+ text-align: center;
+ box-shadow: 0 3px 5px 0 rgba(0,0,0,0.08);
+ transition: box-shadow 0.3s ease-in-out;
+ width: 16rem;
+ padding: 0;
+ margin: 0 10px 20px;
+}
+
+.card:hover {
+ box-shadow: 0 5px 15px 2px rgba(0, 0, 0, 0.2);
+}
+
+.card .nav-link {
+ display: block;
+ padding: 20px 4px 4px 4px;
+}
+
+.card-title, .card-description {
+ margin: 4px;
+ color: #333;
+}
+
+.card-title {
+ font-weight: bold;
+ font-size: 1.75rem
+}
+
+.card-description {
+ font-size: small;
+}
+
+.card-icon {
+ background: radial-gradient(farthest-side at bottom,#eefff0, white);
+ background-position: 50% 100%;
+ background-repeat: no-repeat;
+ background-size: 150% 25%;
+}
+
+.card-icon span {
+ width: 100px;
+ height: 100px;
+ font-size: 80px
+}
diff --git a/static/themes/default/img/FreedomBox-logo-32px-white.png b/static/themes/default/img/FreedomBox-logo-32px-white.png
new file mode 100644
index 000000000..4c6c3382b
Binary files /dev/null and b/static/themes/default/img/FreedomBox-logo-32px-white.png differ
diff --git a/static/themes/default/img/FreedomBox-logo-white.svg b/static/themes/default/img/FreedomBox-logo-white.svg
new file mode 100644
index 000000000..4bad76e63
--- /dev/null
+++ b/static/themes/default/img/FreedomBox-logo-white.svg
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/themes/default/img/apps-background.svg b/static/themes/default/img/apps-background.svg
new file mode 100644
index 000000000..609b2e612
--- /dev/null
+++ b/static/themes/default/img/apps-background.svg
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/themes/default/img/freedombox-logo-background.svg b/static/themes/default/img/freedombox-logo-background.svg
new file mode 100644
index 000000000..afbe934d5
--- /dev/null
+++ b/static/themes/default/img/freedombox-logo-background.svg
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
diff --git a/static/themes/default/img/system-background.svg b/static/themes/default/img/system-background.svg
new file mode 100644
index 000000000..b7bacb738
--- /dev/null
+++ b/static/themes/default/img/system-background.svg
@@ -0,0 +1,62 @@
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+