Merge pull request 'carnet_rouge' (#1) from carnet_rouge into master

Reviewed-on: #1
This commit is contained in:
2023-06-04 08:51:26 +00:00
22 changed files with 389 additions and 2 deletions

2
.idea/Reskreen.iml generated
View File

@@ -7,7 +7,7 @@
<excludeFolder url="file://$MODULE_DIR$/Reskreen/.vs" />
<excludeFolder url="file://$MODULE_DIR$/vehicles/migrations" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">

2
.idea/misc.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (Reskreen)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" />
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -16,11 +16,22 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic import RedirectView
urlpatterns = [
path('', RedirectView.as_view(url='admin/login/', permanent=False), name='/'),
path('admin/', admin.site.urls),
path('accounts/', admin.site.urls),
path('collabs/', include('collabs.urls')),
path('vehicules/', include('vehicles.urls')),
path('caldav/', include('mycaldav.urls')),
#path('collabs_hour/', include('collabs.urls')),
path('carnet_rouge/', include('carnet_rouge.urls')),
path('summernote/', include('django_summernote.urls')),
path('editor/', include('django_summernote.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

0
carnet_rouge/__init__.py Normal file
View File

104
carnet_rouge/admin.py Normal file
View File

@@ -0,0 +1,104 @@
from django.contrib import admin
from carnet_rouge.models import cr_Category, cr_Message
from django.contrib.auth.models import User
from django.contrib.admin import SimpleListFilter
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from django_summernote.admin import SummernoteModelAdmin
class DefaultListFilter(SimpleListFilter):
all_value = '_all'
def default_value(self):
raise NotImplementedError()
def queryset(self, request, queryset):
if self.parameter_name in request.GET and request.GET[self.parameter_name] == self.all_value:
return queryset
if self.parameter_name in request.GET:
return queryset.filter(**{self.parameter_name:request.GET[self.parameter_name]})
return queryset.filter(**{self.parameter_name:self.default_value()})
def choices(self, cl):
yield {
'selected': self.value() == self.all_value,
'query_string': cl.get_query_string({self.parameter_name: self.all_value}, []),
'display': _('All'),
}
for lookup, title in self.lookup_choices:
yield {
'selected': self.value() == force_str(lookup) or (self.value() == None and force_str(self.default_value()) == force_str(lookup)),
'query_string': cl.get_query_string({
self.parameter_name: lookup,
}, []),
'display': title,
}
class StatusFilter(DefaultListFilter):
title = _('Actif ')
parameter_name = 'bEnabled__exact'
def lookups(self, request, model_admin):
return ((0,'Désactivé'), (1,'Activé'))
def default_value(self):
return 1
@admin.register(cr_Message)
class cr_Message_Admin(SummernoteModelAdmin):
summernote_fields = ('sText',)
class Meta:
verbose_name = 'Message carnet rouge'
verbose_name_plural = 'Messages carnet rouge'
def save_model(self, request,obj , form, change):
obj.Author = request.user
obj.sAuthor = request.user.first_name + " " + request.user.last_name
#Get all user of selected group
obj.sDestUsers = "" # reset
users_all = User.objects.filter(groups__name=obj.DestGroup.name)
_con = ""
for usr in users_all:
obj.sDestUsers += f"{_con}[{usr.id}]"
_con = ";"
obj.sNotReadUsers = obj.sDestUsers
obj.save()
def has_change_permission(self, request, obj=None):
if obj is not None and obj.Author != request.user :
return False
return True
def has_delete_permission(self, request, obj=None):
if obj is not None and obj.Author != request.user and not request.user.is_superuser:
return False
return True
always_show_username = True
list_display = ('MessageId','sTitle', 'DestGroup', 'get_dtCreated', 'sAuthor','bEnabled', 'calc_read_quotas')
list_filter = ["sAuthor", StatusFilter]
fields = ["Caterogy", "DestGroup", 'sTitle', "sText", "dtValidityFrom", "dtValidityTo", "bEnabled"]
search_fields = ['sTitle', 'sText']
"""
list_filter = [('dtDate', DateRangeFilter), ('user', admin.RelatedOnlyFieldListFilter),'sBases','type', 'bNoticed']
search_fields = ['userName']
readonly_fields = ["userName"]
"""
# Register your models here.
admin.site.register(cr_Category)

6
carnet_rouge/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class CarnetRougeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'carnet_rouge'

7
carnet_rouge/forms.py Normal file
View 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',)

74
carnet_rouge/models.py Normal file
View File

@@ -0,0 +1,74 @@
import datetime
from django.db import models
from django.conf import settings
from django.contrib.auth.models import Group
from django.utils import timezone
import uuid
from django_quill.fields import QuillField
from django.dispatch import receiver
from django.db.models.signals import pre_save
# Create your models here.
class cr_Category(models.Model):
sName = models.CharField("Désignation", max_length=250)
dtUpdated = models.DateTimeField('date updated', auto_now=True)
dtCreated = models.DateTimeField('date published', auto_now_add=True)
def __str__(self):
return self.sName
class Meta:
verbose_name = "catégorie"
verbose_name_plural = "catégories"
def increment_MessageId():
last_id = cr_Message.objects.all().order_by('MessageId').last()
if not last_id:
return 1
last_id = last_id.MessageId
return last_id + 1
class cr_Message(models.Model):
uuid = models.UUIDField(default=uuid.uuid4(), editable=False, primary_key=True)
MessageId = models.IntegerField("ID Message",editable=False, unique=True, default=increment_MessageId)
Caterogy = models.ForeignKey(cr_Category, on_delete=models.DO_NOTHING, verbose_name="Catégorie")
sDestUsers = models.TextField("Liste des utilisateurs cibles")
sNotReadUsers = models.TextField()
sReadedUsers = models.TextField("Liste des utilisateurs ayant lu", blank=True)
DestGroup = models.ForeignKey(Group, on_delete=models.DO_NOTHING, verbose_name="Groupe de destination")
sTitle = models.CharField("Titre", max_length=120)
sText = models.TextField ("Corps de texte")
dtValidityFrom = models.DateField("Validité depuis",default=timezone.now)
dtValidityTo = models.DateField("Validité jusqu'à", blank=True, null=True)
bEnabled = models.BooleanField("Actif", default=True)
Author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name="Auteur", on_delete=models.SET_NULL, null=True)
sAuthor = models.CharField("Auteur", max_length=120)
dtUpdated = models.DateTimeField('date updated', auto_now=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):
obj = self
n_dest = obj.sDestUsers.count('[')
n_readed = obj.sReadedUsers.count('[')
if n_dest == 0:
return "No dest"
return f"{(n_readed/n_dest)*100}%"
def __str__(self):
return self.sTitle
class Meta:
verbose_name = "message"
verbose_name_plural = "messages"

12
carnet_rouge/static/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
img {
max-width: 100%;
}
footer {
font-size: 12px;
padding: 10px;
background-color: #eee;
}

View 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>

View 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 %}

View File

@@ -0,0 +1,7 @@
<div class="card">
<div class="card-body">
<div>
{{ obj.sText|safe }}
</div>
</div>
</div>

View File

@@ -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 %}

View File

@@ -0,0 +1,19 @@
{% 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 %}
<h2>{{ obj.sTitle }}</h2>
{% 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 %}

View 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>

3
carnet_rouge/tests.py Normal file
View File

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

15
carnet_rouge/urls.py Normal file
View File

@@ -0,0 +1,15 @@
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from carnet_rouge import views
app_name = "carnet_rouge"
urlpatterns = [
path('cr', views.model_form_view, name='model_form_view'),
path('view/<uuid:pk>', views.CrDetailView.as_view(), name='cr_view'),
path('notread', views.CrNotReadView.as_view(), name='cr_not_read_list'),
]

30
carnet_rouge/views.py Normal file
View File

@@ -0,0 +1,30 @@
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.

Binary file not shown.