Ajout de Quill et avancé du dev
This commit is contained in:
@@ -23,5 +23,5 @@ urlpatterns = [
|
|||||||
path('vehicules/', include('vehicles.urls')),
|
path('vehicules/', include('vehicles.urls')),
|
||||||
path('caldav/', include('mycaldav.urls')),
|
path('caldav/', include('mycaldav.urls')),
|
||||||
#path('collabs_hour/', include('collabs.urls')),
|
#path('collabs_hour/', include('collabs.urls')),
|
||||||
path('tinymce/', include('tinymce.urls')),
|
path('carnet_rouge/', include('carnet_rouge.urls')),
|
||||||
]
|
]
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
|
|
||||||
from carnet_rouge.models import cr_Category, cr_Message
|
from carnet_rouge.models import cr_Category, cr_Message
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.admin import SimpleListFilter
|
from django.contrib.admin import SimpleListFilter
|
||||||
@@ -47,6 +48,7 @@ class StatusFilter(DefaultListFilter):
|
|||||||
def default_value(self):
|
def default_value(self):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@admin.register(cr_Message)
|
||||||
class cr_Message_Admin(admin.ModelAdmin):
|
class cr_Message_Admin(admin.ModelAdmin):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Message carnet rouge'
|
verbose_name = 'Message carnet rouge'
|
||||||
@@ -63,16 +65,16 @@ class cr_Message_Admin(admin.ModelAdmin):
|
|||||||
obj.sDestUsers += f"{_con}[{usr.id}]"
|
obj.sDestUsers += f"{_con}[{usr.id}]"
|
||||||
_con = ";"
|
_con = ";"
|
||||||
|
|
||||||
|
obj.sNotReadUsers = obj.sDestUsers
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
def has_change_permission(self, request, obj=None):
|
def has_change_permission(self, request, obj=None):
|
||||||
if obj is not None and obj.Author != request.user:
|
if obj is not None and obj.Author != request.user :
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def has_delete_permission(self, request, obj=None):
|
def has_delete_permission(self, request, obj=None):
|
||||||
if obj is not None and obj.Author != request.user:
|
if obj is not None and obj.Author != request.user and not request.user.is_superuser:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -80,9 +82,11 @@ class cr_Message_Admin(admin.ModelAdmin):
|
|||||||
|
|
||||||
|
|
||||||
always_show_username = True
|
always_show_username = True
|
||||||
list_display = ('id', 'DestGroup', 'sTitle', 'dtCreated', 'sAuthor','bEnabled', 'calc_read_quotas')
|
list_display = ('id', 'DestGroup', 'sTitle', 'get_dtCreated', 'sAuthor','bEnabled', 'calc_read_quotas')
|
||||||
list_filter = ["sAuthor", StatusFilter]
|
list_filter = ["sAuthor", StatusFilter]
|
||||||
fields = ["Caterogy", "DestGroup", 'sTitle', "sText", "dtValidityFrom", "dtValidityTo", "bEnabled"]
|
fields = ["Caterogy", "DestGroup", 'sTitle', "sText", "dtValidityFrom", "dtValidityTo", "bEnabled"]
|
||||||
|
search_fields = ['sTitle', 'sText']
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
list_filter = [('dtDate', DateRangeFilter), ('user', admin.RelatedOnlyFieldListFilter),'sBases','type', 'bNoticed']
|
list_filter = [('dtDate', DateRangeFilter), ('user', admin.RelatedOnlyFieldListFilter),'sBases','type', 'bNoticed']
|
||||||
@@ -96,4 +100,3 @@ class cr_Message_Admin(admin.ModelAdmin):
|
|||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
admin.site.register(cr_Category)
|
admin.site.register(cr_Category)
|
||||||
admin.site.register(cr_Message, cr_Message_Admin)
|
|
7
carnet_rouge/forms.py
Normal file
7
carnet_rouge/forms.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from django import forms
|
||||||
|
from carnet_rouge.models import cr_Message
|
||||||
|
|
||||||
|
class CrForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = cr_Message
|
||||||
|
fields = ('sText',)
|
@@ -3,7 +3,7 @@ from django.db import models
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from tinymce.models import HTMLField
|
from django_quill.fields import QuillField
|
||||||
|
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.db.models.signals import pre_save
|
from django.db.models.signals import pre_save
|
||||||
@@ -26,10 +26,11 @@ class cr_Category(models.Model):
|
|||||||
class cr_Message(models.Model):
|
class cr_Message(models.Model):
|
||||||
Caterogy = models.ForeignKey(cr_Category, on_delete=models.DO_NOTHING, verbose_name="Catégorie")
|
Caterogy = models.ForeignKey(cr_Category, on_delete=models.DO_NOTHING, verbose_name="Catégorie")
|
||||||
sDestUsers = models.TextField("Liste des utilisateurs cibles")
|
sDestUsers = models.TextField("Liste des utilisateurs cibles")
|
||||||
|
sNotReadUsers = models.TextField()
|
||||||
sReadedUsers = models.TextField("Liste des utilisateurs ayant lu", blank=True)
|
sReadedUsers = models.TextField("Liste des utilisateurs ayant lu", blank=True)
|
||||||
DestGroup = models.ForeignKey(Group, on_delete=models.DO_NOTHING)
|
DestGroup = models.ForeignKey(Group, on_delete=models.DO_NOTHING)
|
||||||
sTitle = models.CharField("Titre", max_length=120)
|
sTitle = models.CharField("Titre", max_length=120)
|
||||||
sText = HTMLField("Corps de texte")
|
sText = QuillField ("Corps de texte")
|
||||||
dtValidityFrom = models.DateField("Validité depuis",default=timezone.now)
|
dtValidityFrom = models.DateField("Validité depuis",default=timezone.now)
|
||||||
dtValidityTo = models.DateField("Validité jusqu'à", blank=True, null=True)
|
dtValidityTo = models.DateField("Validité jusqu'à", blank=True, null=True)
|
||||||
bEnabled = models.BooleanField("Actif", default=True)
|
bEnabled = models.BooleanField("Actif", default=True)
|
||||||
@@ -41,6 +42,9 @@ class cr_Message(models.Model):
|
|||||||
dtUpdated = models.DateTimeField('date updated', auto_now=True)
|
dtUpdated = models.DateTimeField('date updated', auto_now=True)
|
||||||
dtCreated = models.DateTimeField('date published', auto_now_add=True)
|
dtCreated = models.DateTimeField('date published', auto_now_add=True)
|
||||||
|
|
||||||
|
def get_dtCreated(self):
|
||||||
|
return self.dtCreated.strftime("%d.%b.%Y %H:%M:%S")
|
||||||
|
|
||||||
def calc_read_quotas(self):
|
def calc_read_quotas(self):
|
||||||
obj = self
|
obj = self
|
||||||
n_dest = obj.sDestUsers.count('[')
|
n_dest = obj.sDestUsers.count('[')
|
||||||
@@ -49,10 +53,9 @@ class cr_Message(models.Model):
|
|||||||
if n_dest == 0:
|
if n_dest == 0:
|
||||||
return "No dest"
|
return "No dest"
|
||||||
|
|
||||||
|
|
||||||
print(f"{n_dest}/{n_readed}")
|
|
||||||
return f"{(n_readed/n_dest)*100}%"
|
return f"{(n_readed/n_dest)*100}%"
|
||||||
|
def __str__(self):
|
||||||
|
return self.sTitle
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "message"
|
verbose_name = "message"
|
||||||
|
12
carnet_rouge/static/bootstrap.min.css
vendored
Normal file
12
carnet_rouge/static/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
carnet_rouge/static/style.css
Normal file
8
carnet_rouge/static/style.css
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
51
carnet_rouge/templates/base.html
Normal file
51
carnet_rouge/templates/base.html
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{% load static %}
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="ko">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Custom CSS -->
|
||||||
|
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||||
|
<link rel="stylesheet" href="{% static 'style.css' %}">
|
||||||
|
<title>django-quill-editor</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrap">
|
||||||
|
<nav class="navbar navbar-expand navbar-dark bg-primary mb-3 ps-3 pe-3">
|
||||||
|
<a href="" class="navbar-brand">Intranet Ambulance Clerc</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01"
|
||||||
|
aria-controls="navbarColor01"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="w-100">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mr-auto">
|
||||||
|
<a href="{% url 'admin:index' %}" class="nav-link" target="_blank">Administration intranet</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'carnet_rouge:cr_not_read_list' %}" target="_blank">Repository</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
<footer class="mt-2 text-center">© 2023 <a href="https://ambulance-clerc.ch"
|
||||||
|
target="_blank">Ambulance Clerc</a></footer>
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
19
carnet_rouge/templates/carnet_rouge/base_cr.html
Normal file
19
carnet_rouge/templates/carnet_rouge/base_cr.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row d-flex align-items-center mb-3">
|
||||||
|
<div class="col-125 col-md-12 mb-sm-2 mb-xs-2">
|
||||||
|
<h2 class="mb-0">{% block title %}title{% endblock %}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-12 col-lg-9">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% block cr_content %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
7
carnet_rouge/templates/carnet_rouge/cr_message.html
Normal file
7
carnet_rouge/templates/carnet_rouge/cr_message.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div>
|
||||||
|
{{ obj.sText.html|safe }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,6 @@
|
|||||||
|
{% extends 'carnet_rouge/base_cr.html' %}
|
||||||
|
|
||||||
|
{% block title %}<h2>Détail du message: {{ object.sTitle }}</h2>{% endblock %}
|
||||||
|
{% block cr_content %}
|
||||||
|
{% include 'carnet_rouge/cr_message.html' with obj=object %}
|
||||||
|
{% endblock %}
|
18
carnet_rouge/templates/carnet_rouge/cr_message_list.html
Normal file
18
carnet_rouge/templates/carnet_rouge/cr_message_list.html
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{% extends 'carnet_rouge/base_cr.html' %}
|
||||||
|
|
||||||
|
{% block title %}Messages non lus{% endblock %}
|
||||||
|
{% block cr_content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
{% if object_list %}
|
||||||
|
{% for obj in object_list %}
|
||||||
|
{% include 'carnet_rouge/cr_message.html' with obj=obj %}
|
||||||
|
{% if not forloop.last %}
|
||||||
|
<hr>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p>There is no post.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
15
carnet_rouge/templates/form_view.html
Normal file
15
carnet_rouge/templates/form_view.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
{{ form.media }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
test
|
||||||
|
<form action="" method="POST">{% csrf_token %}
|
||||||
|
{{ form.sText }}
|
||||||
|
</form>
|
||||||
|
{{ obj.sText }}
|
||||||
|
</body>
|
||||||
|
</html>
|
20
carnet_rouge/urls.py
Normal file
20
carnet_rouge/urls.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
from carnet_rouge import views
|
||||||
|
|
||||||
|
app_name = "carnet_rouge"
|
||||||
|
urlpatterns = [
|
||||||
|
path('cr', views.model_form_view, name='model_form_view'),
|
||||||
|
path('view/<int:pk>', views.CrDetailView.as_view(), name='cr_view'),
|
||||||
|
path('notread', views.CrNotReadView.as_view(), name='cr_not_read_list'),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
|
@@ -1,3 +1,29 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from carnet_rouge.forms import CrForm
|
||||||
|
from django.views.generic import ListView, UpdateView, DetailView, FormView, CreateView
|
||||||
|
|
||||||
|
from carnet_rouge.models import *
|
||||||
|
|
||||||
|
def model_form_view(request):
|
||||||
|
return render(request, "form_view.html", {'form': CrForm()})
|
||||||
|
|
||||||
|
class CrDetailView(DetailView):
|
||||||
|
model = cr_Message
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["test"] = timezone.now()
|
||||||
|
return context
|
||||||
|
|
||||||
|
class CrNotReadView(ListView):
|
||||||
|
model = cr_Message
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["test"] = timezone.now()
|
||||||
|
return context
|
||||||
|
def cr_view(request, id):
|
||||||
|
print(id)
|
||||||
|
cr = cr_Message.objects.get(pk=id)
|
||||||
|
return render(request, "form_view.html", {'form': CrForm(), 'obj': cr})
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
@@ -56,4 +56,4 @@ x-wr-timezone==0.0.5
|
|||||||
xhtml2pdf==0.2.7
|
xhtml2pdf==0.2.7
|
||||||
zopfli==0.1.9
|
zopfli==0.1.9
|
||||||
django-autologin
|
django-autologin
|
||||||
django-tinymce
|
django-quill-editor
|
Reference in New Issue
Block a user