Merge pull request 'carnet_rouge' (#1) from carnet_rouge into master
Reviewed-on: #1
This commit is contained in:
2
.idea/Reskreen.iml
generated
2
.idea/Reskreen.iml
generated
@@ -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
2
.idea/misc.xml
generated
@@ -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>
|
||||
|
BIN
Reskreen/static/img/logo.png
Normal file
BIN
Reskreen/static/img/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 311 KiB |
@@ -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
0
carnet_rouge/__init__.py
Normal file
104
carnet_rouge/admin.py
Normal file
104
carnet_rouge/admin.py
Normal 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
6
carnet_rouge/apps.py
Normal 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
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',)
|
74
carnet_rouge/models.py
Normal file
74
carnet_rouge/models.py
Normal 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
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|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 %}
|
19
carnet_rouge/templates/carnet_rouge/cr_message_list.html
Normal file
19
carnet_rouge/templates/carnet_rouge/cr_message_list.html
Normal 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 %}
|
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>
|
3
carnet_rouge/tests.py
Normal file
3
carnet_rouge/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
15
carnet_rouge/urls.py
Normal file
15
carnet_rouge/urls.py
Normal 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
30
carnet_rouge/views.py
Normal 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.
|
BIN
vehicles/static/vehicles/images/Thumbs.db
Normal file
BIN
vehicles/static/vehicles/images/Thumbs.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user