Merge branch 'install-bulma' into 'develop'

Semblant d'interface graphique

See merge request hashbangfr/la_chariotte!7
This commit is contained in:
Laetitia Getti 2023-05-02 14:51:50 +00:00
commit 675fdac7a3
20 changed files with 10794 additions and 129 deletions

3
.gitignore vendored
View file

@ -2,3 +2,6 @@ __pycache__/
coverage.xml
.coverage
la_chariotte.egg-info/
node_modules
/static/*
/media/*

View file

@ -17,6 +17,24 @@ pip install -r requirements.txt
pip install -r dev-requirements.txt
```
## Travailler sur le frontend
check sass version
```bash
sass --version
# used for developement: 1.59.3 compiled with dart2js 2.19.4
```
watch for changes when updating scss files (from project root)
```bash
sass --watch --no-source-map ./la_chariotte/static/sass/style.sass:./la_chariotte/static/css/app.css
```
OR compile css only once (from project root)
```bash
sass --no-source-map ./la_chariotte/static/sass/style.sass:./la_chariotte/static/css/app.css
```
## Lancer les tests
Lancer les tests avec pytest :

View file

@ -2,13 +2,14 @@
{% block title %}Connexion{% endblock %}
{% block content_title %}Connexion{% endblock %}
{% block content %}
<h2>Connexion</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Se connecter</button>
<a href="{% url 'accounts:signup' %}">Créer un compte</button>
<button class="button is-primary" type="submit">Se connecter</button>
<a href="{% url 'accounts:signup' %}">Créer un compte</a>
</form>
{% endblock %}

View file

@ -1,13 +1,13 @@
{% extends 'base.html' %}
{% block title %}Créer un compte{% endblock %}
{% block content_title %}Créer un compte{% endblock %}
{% block content %}
<h2>Créer un compte</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Valider</button>
<button class="button is-primary" type="submit">Valider</button>
</form>
{% endblock %}

View file

@ -1,48 +1,45 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Commandes groupées {{ grouped_order.id }}</title>
</head>
<body>
<p>Détail de la commande groupée {{ grouped_order.id }}, avec la liste des produits associés</p>
<br>
<p>{{ grouped_order }}
<p>Organisateur·ice : {{ grouped_order.orga }}</p>
<p>Date de livraison : {{ grouped_order.delivery_date }}</p>
{% extends 'base.html' %}
{% if not user.is_authenticated %}
<p>Vous êtes l'organisateur·ice de cette commande groupée ?
<a href="{% url 'order:grouped_order_overview' grouped_order.id %}">
Connectez-vous pour accéder à la page de gestion</a>
</p>
{% endif %}
{% block title %}{{ grouped_order }}{% endblock %}
{% if user == grouped_order.orga %}
<a href="{% url 'order:grouped_order_overview' grouped_order.id %}">
Page de gestion de la commande groupée</a>
{% endif %}
{% block content %}
<p>Détail de la commande groupée {{ grouped_order.id }}, avec la liste des produits associés</p>
<br>
<p>{{ grouped_order }}
<p>Organisateur·ice : {{ grouped_order.orga }}</p>
<p>Date de livraison : {{ grouped_order.delivery_date }}</p>
<p>les produits disponibles pour cette commande groupée : </p>
<ul>
{% if not user.is_authenticated %}
<p>Vous êtes l'organisateur·ice de cette commande groupée ?
<a href="{% url 'order:grouped_order_overview' grouped_order.id %}">
Connectez-vous pour accéder à la page de gestion</a>
</p>
{% endif %}
{% if user == grouped_order.orga %}
<a href="{% url 'order:grouped_order_overview' grouped_order.id %}">
Page de gestion de la comande groupée</a>
{% endif %}
<p>les produits disponibles pour cette commande groupée : </p>
<ul>
{% for item in grouped_order.item_set.all %}
<li>
{{ item }}
</li>
{% endfor %}
</ul>
<form action="{% url 'order:order' grouped_order.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ grouped_order }}</h1></legend>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
{% for item in grouped_order.item_set.all %}
<li>
{{ item }}
</li>
{% endfor %}
</ul>
<form action="{% url 'order:order' grouped_order.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ grouped_order }}</h1></legend>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
{% for item in grouped_order.item_set.all %}
<input type="radio" name="item" id="item{{ forloop.counter }}" value="{{ item.id }}">
<label for="item{{ forloop.counter }}">{{ item.name }}</label><br>
{% endfor %}
</fieldset>
<input type="submit" value="Order">
</form>
</body>
</html>
<input type="radio" name="item" id="item{{ forloop.counter }}" value="{{ item.id }}">
<label for="item{{ forloop.counter }}">{{ item.name }}</label><br>
{% endfor %}
</fieldset>
<input type="submit" value="Order">
</form>
{% endblock %}

View file

@ -1,34 +1,31 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Commandes groupées {{ grouped_order.id }}</title>
</head>
<body>
<p>Vue d'organisation de la commande groupée {{ grouped_order.id }}, avec les produits commandés et les commandes individuelles</p>
<br>
<p>{{ grouped_order }}
<p>Organisateur·ice : {{ grouped_order.orga }}</p>
<p>Date de livraison : {{ grouped_order.delivery_date }}</p>
{% extends 'base.html' %}
les produits commandés pour cette commande groupée :
<ul>
{% for item in grouped_order.item_set.all %}
<li>
{{ item }}, avec {{ item.ordered_nb }} commande{{ item.ordered_nb|pluralize }}
</li>
{% endfor %}
</ul>
{% block title %}{{ grouped_order }} - Organisateur·ice{% endblock %}
les commandes passées pour cette commande groupée :
<ul>
{% for order in grouped_order.order_set.all %}
<li>
{{ order }} : {{ order.ordered_items.count }} produits commandés
</li>
{% endfor %}
</ul>
{% block content %}
<p>Vue d'organisation de la commande groupée {{ grouped_order.id }}, avec les produits commandés et les commandes individuelles</p>
<br>
<p>{{ grouped_order }}
<p>Organisateur·ice : {{ grouped_order.orga }}</p>
<p>Date de livraison : {{ grouped_order.delivery_date }}</p>
<a href={% url 'order:grouped_order_detail' grouped_order.id %}>Retour à la page de commande</a>
</body>
</html>
les produits commandés pour cette commande groupée :
<ul>
{% for item in grouped_order.item_set.all %}
<li>
{{ item }}, avec {{ item.ordered_nb }} commande{{ item.ordered_nb|pluralize }}
</li>
{% endfor %}
</ul>
les commandes passées pour cette commande groupée :
<ul>
{% for order in grouped_order.order_set.all %}
<li>
{{ order }} : {{ order.ordered_items.count }} produits commandés
</li>
{% endfor %}
</ul>
<a href={% url 'order:grouped_order_detail' grouped_order.id %}>Retour à la page de commande</a>
{% endblock %}

View file

@ -1,48 +1,86 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Commandes groupées - index</title>
</head>
<body>
<p>Index des commandes que l'utilisateur·ice connecté·e organise</p>
{% extends 'base.html' %}
{% if grouped_order_list.incoming_grouped_orders or grouped_order_list.crossed_deadline_grouped_orders or grouped_order_list.old_grouped_orders %}
{% if grouped_order_list.incoming_grouped_orders %}
<p>Commandes groupées à venir :</p>
<ul>
{% block title %}Mes commandes groupées{% endblock %}
{% block content_title %}Commandes groupées que vous organisez{% endblock %}
{% block content %}
{% if grouped_order_list.incoming_grouped_orders or grouped_order_list.crossed_deadline_grouped_orders or grouped_order_list.old_grouped_orders %}
{% if grouped_order_list.incoming_grouped_orders %}
<p class="is-size-4">Commandes groupées à venir</p>
<table class="table">
<thead>
<tr>
<th>Nom</th>
<th>Livraison</th>
<th>Fin des commandes</th>
<th>Nombre de commandes</th>
<th>Voir</th>
</tr>
</thead>
<tbody>
{% for gr_order in grouped_order_list.incoming_grouped_orders %}
<li>
<a href="{% url 'order:grouped_order_detail' gr_order.id %}"
>{{gr_order.name}}</a>
</li>
<tr>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">{{ gr_order }}</a></td>
<td>{{ gr_order.delivery_date }}</td>
<td>{{ gr_order.deadline }}</td>
<td>Nb de commandes</td>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">Détail </a><a href="{% url 'order:grouped_order_overview' gr_order.id %}">Organisation</a></td>
</tr>
{% endfor %}
</ul>
{% endif %}
{% if grouped_order_list.crossed_deadline_grouped_orders %}
<p>Livraison à venir, date limite de commande dépassée :</p>
<ul>
</tbody>
</table>
{% endif %}
{% if grouped_order_list.crossed_deadline_grouped_orders %}
<p class="is-size-4">Livraison à venir, date limite de commande dépassée</p>
<table class="table">
<thead>
<tr>
<th>Nom</th>
<th>Livraison</th>
<th>Fin des commandes</th>
<th>Nombre de commandes</th>
<th>Voir</th>
</tr>
</thead>
<tbody>
{% for gr_order in grouped_order_list.crossed_deadline_grouped_orders %}
<li>
<a href="{% url 'order:grouped_order_detail' gr_order.id %}"
>{{gr_order.name}}</a>
</li>
<tr>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">{{ gr_order }}</a></td>
<td>{{ gr_order.delivery_date }}</td>
<td>{{ gr_order.deadline }}</td>
<td>Nb de commandes</td>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">Détail </a><a href="{% url 'order:grouped_order_overview' gr_order.id %}">Organisation</a></td>
</tr>
{% endfor %}
</ul>
{% endif %}
{% if grouped_order_list.old_grouped_orders %}
<p>Livraison passée :</p>
<ul>
</tbody>
</table>
{% endif %}
{% if grouped_order_list.old_grouped_orders %}
<p class="is-size-4">Anciennes commandes</p>
<table class="table">
<thead>
<tr>
<th>Nom</th>
<th>Livraison</th>
<th>Fin des commandes</th>
<th>Nombre de commandes</th>
<th>Voir</th>
</tr>
</thead>
<tbody>
{% for gr_order in grouped_order_list.old_grouped_orders %}
<li>
<a href="{% url 'order:grouped_order_detail' gr_order.id %}"
>{{gr_order.name}}</a>
</li>
<tr>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">{{ gr_order }}</a></td>
<td>{{ gr_order.delivery_date }}</td>
<td>{{ gr_order.deadline }}</td>
<td>Nb de commandes</td>
<td><a href="{% url 'order:grouped_order_detail' gr_order.id %}">Détail </a><a href="{% url 'order:grouped_order_overview' gr_order.id %}">Organisation</a></td>
</tr>
{% endfor %}
</ul>
{% endif %}
{% else %}
<p>Pas de commande groupée pour l'instant</p>
{% endif %}
</body>
</html>
</tbody>
</table>
{% endif %}
{% else %}
<p>Pas de commande groupée pour l'instant</p>
{% endif %}
{% endblock %}

View file

@ -82,7 +82,7 @@ class TestGroupedOrderIndexView:
assert "Pas de commande groupée pour l'instant" not in response.content.decode()
assert "Commandes groupées à venir" in response.content.decode()
assert "Livraison à venir" in response.content.decode()
assert "Livraison passée" in response.content.decode()
assert "Anciennes commandes" in response.content.decode()
assert len(response.context["grouped_order_list"]["old_grouped_orders"]) == 1
assert (
len(
@ -123,7 +123,7 @@ class TestGroupedOrderIndexView:
assert "Pas de commande groupée pour l'instant" not in response.content.decode()
assert "Commandes groupées à venir" not in response.content.decode()
assert "Livraison à venir" not in response.content.decode()
assert "Livraison passée" in response.content.decode()
assert "Anciennes commandes" in response.content.decode()
assert len(response.context["grouped_order_list"]["old_grouped_orders"]) == 1
assert (
len(
@ -156,7 +156,7 @@ class TestGroupedOrderIndexView:
assert "Pas de commande groupée pour l'instant" not in response.content.decode()
assert "Commandes groupées à venir" in response.content.decode()
assert "Livraison à venir" not in response.content.decode()
assert "Livraison passée" not in response.content.decode()
assert "Anciennes commandes" not in response.content.decode()
assert len(response.context["grouped_order_list"]["old_grouped_orders"]) == 0
assert (
len(

View file

@ -15,6 +15,9 @@ from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
BASE_URL = "http://127.0.0.1:8000" # to be moved to settings/dev.py
BASE_URL = os.getenv("BASE_URL")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
@ -117,7 +120,7 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/
LANGUAGE_CODE = "en-us"
LANGUAGE_CODE = "fr-FR"
TIME_ZONE = "Europe/Paris"
@ -130,6 +133,12 @@ USE_TZ = True
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = "static/"
STATICFILES_DIRS = ["la_chariotte/static"]
STATIC_ROOT = os.getenv("STATIC_ROOT", BASE_DIR / "static")
MEDIA_URL = "/media/"
MEDIA_ROOT = os.getenv("MEDIA_ROOT", BASE_DIR / "media")
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View file

@ -0,0 +1,3 @@
.button.is-light, .buttons.is-light:hover, .buttons.is-light.is-hovered
border: $betterave 1px solid !important
color: $betterave !important

View file

@ -0,0 +1,9 @@
@media screen and (min-width: $min-desktop)
.content
margin: $base
margin-left: $side-nav-width + $base
@media screen and (max-width: $max-tablet)
.content
margin: $small
padding-top: $navbar-height

View file

@ -0,0 +1,6 @@
body
min-height: 100vh
background-color: $background
a
color: $betterave

View file

@ -0,0 +1,44 @@
// Desktop
@media screen and (min-width: $min-desktop)
.navbar.side-nav
right: inherit
height: 100vh
width: $side-nav-width
padding: 20px 10px
.side-nav
&.navbar, .navbar-brand, .navbar-menu, .navbar-start
flex-direction: column
overflow-y: auto
.navbar-brand .navbar-item
padding: 0 3px 15px 3px
img
max-height: 150px
.navbar.top-nav
margin-left: $side-nav-width
border-bottom: $beige 1px solid
.desktop-hidden
display: none
// Mobile
@media screen and (max-width: $max-tablet)
.navbar.side-nav
.navbar-brand .navbar-item
padding-top: 3px
padding-bottom: 3px
img
max-height: 46px
.navbar-menu.is-active
padding: 10px 10px
.navbar.top-nav
display: none
// Global
a.navbar-item:hover
color: $bright-black
background-color: $beige
border-radius: $border-radius

View file

@ -0,0 +1,38 @@
// colors
$betterave: #A52951
$beige: #e9b049
$bright-black: #280a13
$primary: $betterave
$info: $betterave
$text: $bright-black
// Navbar
$side-nav-width: 220px
// screen sizes
$max-mobile: 768px
$min-tablet: 769px
$max-tablet: 1023px
$min-desktop: 1024px
$max-desktop: 1215px
$min-widescreen: 1216px
// spacing
$super-tiny: 4px
$tiny: 8px
$small: 16px // = 1em
$base: 24px // = 2em
$large: 48px
$xlarge: 64px
// border
$border-radius: 2px
// // font size
// $font-size-desktop: 22px
// $font-size-mobile: 13px
// $font-size-small-desktop: 16px
// $font-size-small-mobile: 11px
// $font-size-large-desktop: 24px
// $font-size-large-mobile: 16px

View file

@ -0,0 +1,15 @@
// 1. Import the initial variables
@import "../../node_modules/bulma/sass/utilities/initial-variables"
// 2. Set your own initial variables
@import "./base/variables"
// @import "./base/fonts"
// 3. Import the rest of Bulma
@import "../../node_modules/bulma/bulma"
// 4. Import your stuff here
@import "./base/global"
@import "./base/navbar"
@import "./base/content"
@import "./base/buttons"

View file

@ -1,13 +1,142 @@
{% load static %}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:type" content="website">
<meta property="og:locale" content="fr_FR" />
<meta property="og:site_name" content="La chariotte">
<meta property="og:url" content="{{ BASE_URL }}{{ request.path }}">
<title>{% block title %}{% endblock %} - La Chariotte</title>
{% block css %}
<link rel="stylesheet" href="{% static 'css/app.css' %}">
{% block extra_css %}{% endblock extra_css %}
{% endblock css %}
<link rel="shortcut icon" href="{% static 'img/icons/chariotte.ico' %}">
</head>
<body>
<main>
{% block content %}
{% endblock %}
<!-- Top navbar -->
<nav class="top-nav navbar">
<!-- Navbar brand : always visible (all screen sizes)-->
<div class="navbar-brand">
<p class="navbar-item is-size-4 has-text-weight-semibold">
{% block content_title %}Bienvenue :){% endblock %}
</p>
</div>
<div class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
{% if user.is_authenticated %}
<a class="button is-light" href="{% url 'accounts:logout' %}">
Se déconnecter
</a>
{% else %}
<a class="button is-light" href="{% url 'accounts:signup' %}">
<strong>Créer un compte</strong>
</a>
<a class="button is-primary" href="{% url 'accounts:login' %}">
Se connecter
</a>
{% endif %}
</div>
</div>
</div>
</div>
</nav>
<!-- End Top navbar -->
<!-- Side navbar -->
<nav class="side-nav navbar is-fixed-top is-flex-desktop" role="navigation" aria-label="main navigation">
<!-- Navbar brand : always visible (all screen sizes)-->
<div class="navbar-brand">
<a class="navbar-item" href="{% url 'home' %}">
<img src="{% static 'img/logos/logo_la_chariotte.png' %}">
</a>
{% if user.is_authenticated %}
<a class="navbar-item desktop-hidden" href="{% url 'order:index' %}">
Mes commandes
</a>
{% endif %}
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<!-- Navbar menu : only visible on desktop-->
<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="{% url 'home' %}">
Accueil
</a>
<a class="navbar-item" href="{% url 'order:index' %}">
Mes commandes
</a>
<a class="navbar-item" href="{% url 'order:index' %}">
Créer une commande groupée
</a>
<a class="navbar-item" href="{% url 'order:index' %}">
Rejoindre une commande groupée
</a>
</div>
<hr>
<div class="navbar-item desktop-hidden">
<div class="buttons">
{% if user.is_authenticated %}
<a class="button is-light" href="{% url 'accounts:logout' %}">
Se déconnecter
</a>
{% else %}
<a class="button is-light" href="{% url 'accounts:signup' %}">
<strong>Créer un compte</strong>
</a>
<a class="button is-primary" href="{% url 'accounts:login' %}">
Se connecter
</a>
{% endif %}
</div>
</div>
</div>
</nav>
<!-- End Navbar -->
<div class="content">
{% block content %}
{% endblock %}
</div>
</main>
</body>
</html>
</html>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
});
</script>

View file

@ -2,6 +2,10 @@
{% block title %}Accueil{% endblock %}
{% block content_title %}
Bienvenue{% if user.is_authenticated %}, {{ user.username }}{% else %}&nbsp;!{% endif %}
{% endblock %}
{% block content %}
{% if user.is_authenticated %}
Hi {{ user.username }}!
@ -13,7 +17,7 @@
</p>
{% else %}
<p>You are not logged in</p>
<a href="{% url 'accounts:login' %}">Se connecter</a>
<a class="button is-primary" href="{% url 'accounts:login' %}">Se connecter</a>
{% endif %}
{% endblock %}