Cropper bei Profilen hinzugefügt

This commit is contained in:
holger.trampe 2020-01-19 22:41:23 +01:00
parent 6f4544af64
commit f6f4b8f578
16 changed files with 3880 additions and 59 deletions

View File

@ -12,7 +12,6 @@ https://docs.djangoproject.com/en/2.2/ref/settings/
import os import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -120,6 +119,7 @@ CKEDITOR_CONFIGS = {
} }
# Database # Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',

View File

@ -5,16 +5,14 @@
<div class="content-section"> <div class="content-section">
<h3>{{request.user.profile.agency.name}}</h3> <h3>{{request.user.profile.agency.name}}</h3>
<hr> <hr>
<h4>Organigramm</h4> <h4>Organigramm</h4>
{% if invisible_users > 0%}
<div class="alert alert-danger" role="alert">
Achtung! {{invisible_users}} Mitarbeiter sind anderen Mitarbeitern untergeordnet, die nicht im Organigramm sichtbar sein sollen. Bitte prüfen sie die Zuordnung der übergeordneten Mitarbeiter!
</div>
{% endif %}
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div id="diagram"></div> <div id="diagram"></div>
</div>
<div id="spinner" class="text-center" style="margin-top: 15%; width: 100%; height: 100%; display: none;margin-left:auto;
margin-right:auto;">
<div class="spinner-border text-danger" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> </div>
</div> </div>
@ -22,9 +20,6 @@ margin-right:auto;">
<script type="text/javascript"> <script type="text/javascript">
var data = [ var data = [
{ 'id' : '{{request.user.profile.agency.pk}}', 'parent' : "", 'role': "", 'name': '{{request.user.profile.agency.name}}', 'color': '#71AF17', "imageUrl": "", 'children' : []}, { 'id' : '{{request.user.profile.agency.pk}}', 'parent' : "", 'role': "", 'name': '{{request.user.profile.agency.name}}', 'color': '#71AF17', "imageUrl": "", 'children' : []},
{% for u in agencyuser %} {% for u in agencyuser %}
@ -36,7 +31,6 @@ var data = [
{% endfor %} {% endfor %}
]; ];
//Check for Agency and User-IDs - dont touch the userid for URLs! //Check for Agency and User-IDs - dont touch the userid for URLs!
for(i = 0; i < data.length; i++){ for(i = 0; i < data.length; i++){
for(k = 0; k < data.length; k++){ for(k = 0; k < data.length; k++){
@ -49,7 +43,6 @@ for(i = 0; i < data.length; i++){
data[m]['parent'] = data[m]['parent']*10; data[m]['parent'] = data[m]['parent']*10;
} }
} }
} }
} }
} }
@ -71,13 +64,13 @@ function unflatten(arr) {
for (var id in mappedArr) { for (var id in mappedArr) {
if (mappedArr.hasOwnProperty(id)) { if (mappedArr.hasOwnProperty(id)) {
mappedElem = mappedArr[id]; mappedElem = mappedArr[id];
// If the element is not at the root level, add it to its parent array of children. // If the element is not at the root level, add it to its parent array of children.
if (mappedElem.parent) { if (mappedElem.parent) {
mappedArr[mappedElem['parent']]['children'].push(mappedElem); mappedArr[mappedElem['parent']]['children'].push(mappedElem);
} }
// If the element is at the root level, add it to first level elements array. // If the element is at the root level, add it to first level elements array.
else { else {
tree.push(mappedElem); tree.push(mappedElem);
} }
} }
@ -90,7 +83,7 @@ var html = ['<ul class="tree">'];
//Create UL-LI-List for tree //Create UL-LI-List for tree
function createList(arr) { function createList(arr) {
html.push('<ul>'); html.push('<ul>');
$.each(arr, function(i, val) { $.each(arr, function(i, val) {
if(val.parent == ""){ if(val.parent == ""){
html.push('<li><a href="#"><h4>' + val.name + "</h4></a>"); html.push('<li><a href="#"><h4>' + val.name + "</h4></a>");
} }
@ -100,7 +93,7 @@ function createList(arr) {
if (val.children) { if (val.children) {
createList(val.children) createList(val.children)
} }
html.push('</li>'); html.push('</li>');
}); });
html.push('</ul>'); html.push('</ul>');
} }
@ -115,7 +108,6 @@ for(i = 0; i < html.length; i++){
} }
} }
} }
function goToUser(id){ function goToUser(id){
window.location.href = "/orga/single/"+id; window.location.href = "/orga/single/"+id;
} }

View File

@ -9,27 +9,23 @@ import webcolors
@login_required @login_required
def mainorga(request): def mainorga(request):
#leader = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__func='lead'))
#if len(leader) > 0:
# leader = leader[0]
#else:
# leader = None
agencyuser = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__visible=True).order_by('-id')) agencyuser = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__visible=True).order_by('-id'))
nonvisibleuser = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__visible=False).order_by('-id'))
invisible_users = 0;
# Check, if parented users are invisible. Remove them and give user an info!
for ele in nonvisibleuser:
for vis in agencyuser:
if vis.profile.parent.profile.pk == ele.pk:
agencyuser.remove(vis)
invisible_users += 1
#indoor = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__func='indoor'))
#external = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__func='external'))
#trainee = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__func='trainee'))
context = { context = {
'active_link' : 'orga', 'active_link' : 'orga',
'agencyuser' : agencyuser 'agencyuser' : agencyuser,
'invisible_users' : invisible_users
} }
# 'leader' : leader,
# 'indoor' : indoor,
# 'external' : external,
# 'trainee' : trainee
return render(request, 'orga/orga_main.html', context) return render(request, 'orga/orga_main.html', context)

View File

@ -66,6 +66,8 @@ Klasse für die Zusatzinfos eines Nutzers.
- Aufgaben - Aufgaben
''' '''
class Profile(models.Model): class Profile(models.Model):
# AGENCY TASKS # AGENCY TASKS
@ -88,7 +90,6 @@ class Profile(models.Model):
image = models.ImageField(default='userprofilepics/default.jpg', upload_to='userprofilepics', blank=True) image = models.ImageField(default='userprofilepics/default.jpg', upload_to='userprofilepics', blank=True)
compfunc = models.CharField(max_length=60, blank=True) compfunc = models.CharField(max_length=60, blank=True)
visible = models.BooleanField(default=True) visible = models.BooleanField(default=True)
def __str__(self): def __str__(self):
return f'{self.user.last_name}' return f'{self.user.last_name}'
@ -98,7 +99,7 @@ class Profile(models.Model):
return reverse('users-update', kwargs={'pk':self.pk}) return reverse('users-update', kwargs={'pk':self.pk})
# Erst Oberklasse speichern, dann Bild verkleinern # Erst Oberklasse speichern, dann Bild verkleinern
'''
def save(self, **kwargs): def save(self, **kwargs):
super().save() super().save()
if self.image: if self.image:
@ -114,7 +115,7 @@ class Profile(models.Model):
wsize = int((float(img.size[0]) * float(hpercent))) wsize = int((float(img.size[0]) * float(hpercent)))
img = img.resize((wsize, baseheight), Image.ANTIALIAS) img = img.resize((wsize, baseheight), Image.ANTIALIAS)
img.save(self.image.path) img.save(self.image.path)
'''
@property @property
def get_photo_url(self): def get_photo_url(self):
if self.image and hasattr(self.image, 'url'): if self.image and hasattr(self.image, 'url'):
@ -124,7 +125,8 @@ class Profile(models.Model):
# PERMISSIONS - Über alle Modelle hinweg, in der url.py wird dann die route verhindert! # PERMISSIONS - Über alle Modelle hinweg, in der url.py wird dann die route verhindert!
# Im template: if perms.users.PERMISSION # Im template: if perms.users.PERMISSION
class Meta: class Meta:
permissions = [ permissions = [
('agency_change', 'Agenturinformationen verändern'), ('agency_change', 'Agenturinformationen verändern'),
('users_usermanagement', 'Benutzer bearbeiten'), ('users_usermanagement', 'Benutzer bearbeiten'),
@ -136,3 +138,4 @@ class Profile(models.Model):
] ]

View File

@ -0,0 +1,9 @@
/*!
* Cropper.js v1.5.6
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2019-10-04T04:33:44.164Z
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}

3616
users/static/users/js/cropper.min.js vendored Normal file

File diff suppressed because it is too large Load Diff

73
users/static/users/js/jquery-cropper.js vendored Normal file
View File

@ -0,0 +1,73 @@
/*!
* jQuery Cropper v1.0.1
* https://fengyuanchen.github.io/jquery-cropper
*
* Copyright 2018-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2019-10-19T08:48:33.062Z
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery'), require('cropperjs')) :
typeof define === 'function' && define.amd ? define(['jquery', 'cropperjs'], factory) :
(global = global || self, factory(global.jQuery, global.Cropper));
}(this, function ($, Cropper) { 'use strict';
$ = $ && $.hasOwnProperty('default') ? $['default'] : $;
Cropper = Cropper && Cropper.hasOwnProperty('default') ? Cropper['default'] : Cropper;
if ($ && $.fn && Cropper) {
var AnotherCropper = $.fn.cropper;
var NAMESPACE = 'cropper';
$.fn.cropper = function jQueryCropper(option) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var result;
this.each(function (i, element) {
var $element = $(element);
var isDestroy = option === 'destroy';
var cropper = $element.data(NAMESPACE);
if (!cropper) {
if (isDestroy) {
return;
}
var options = $.extend({}, $element.data(), $.isPlainObject(option) && option);
cropper = new Cropper(element, options);
$element.data(NAMESPACE, cropper);
}
if (typeof option === 'string') {
var fn = cropper[option];
if ($.isFunction(fn)) {
result = fn.apply(cropper, args);
if (result === cropper) {
result = undefined;
}
if (isDestroy) {
$element.removeData(NAMESPACE);
}
}
}
});
return result !== undefined ? result : this;
};
$.fn.cropper.Constructor = Cropper;
$.fn.cropper.setDefaults = Cropper.setDefaults;
$.fn.cropper.noConflict = function noConflict() {
$.fn.cropper = AnotherCropper;
return this;
};
}
}));

View File

@ -13,7 +13,7 @@
<!-- Custom fonts for this template--> <!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com"> <link rel="canonical" href="https://www.digitale-agentur.com">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
@ -32,6 +32,9 @@
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote.js"></script>
<!-- CROPPER -->
<link href="{% static 'users/css/cropper.min.css' %}" rel="stylesheet">
<!-- TABLE SORT --> <!-- TABLE SORT -->
<!--<link rel="stylesheet" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css">--> <!--<link rel="stylesheet" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css">-->
@ -331,6 +334,8 @@
<!-- CUSTOM FONT --> <!-- CUSTOM FONT -->
<link href="{% static 'users/css/custom.css' %}" rel="stylesheet"> <link href="{% static 'users/css/custom.css' %}" rel="stylesheet">
<!-- TABLE SORT --> <!-- TABLE SORT -->
<!--<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>--> <!--<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>-->

View File

@ -1,11 +1,14 @@
{% extends "users/base.html" %} {% extends "users/base.html" %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load static %}
{% block content %} {% block content %}
<script src="{% static 'users/js/cropper.min.js' %}"></script>
<script src="{% static 'users/js/jquery-cropper.js' %}"></script>
<div class="content-section"> <div class="content-section">
<div class="media"> <div class="media">
<img class="img-profile " width="17%" src="{{ prof_user.profile.get_photo_url }}"> <img class="img-profile " id="profpic" width="17%" src="{{ prof_user.profile.get_photo_url }}">
<div class="media-body col-5"> <div class="media-body col-5">
<h2 class="account-heading">Profil von {{ prof_user.first_name }} {{ prof_user.last_name }}</h2> <h2 class="account-heading">Profil von {{ prof_user.first_name }} {{ prof_user.last_name }}</h2>
<hr> <hr>
<div class="row mt-2"> <div class="row mt-2">
<div class="col-md-6"> <div class="col-md-6">
@ -41,13 +44,13 @@
</div> </div>
<!-- Für das Speichern der Bilder enctype --> <!-- Für das Speichern der Bilder enctype -->
<div class="col-7 mt-5"> <div class="col-7 mt-5">
<form method="POST" enctype="multipart/form-data"> <form method="POST" id="newprofiledata" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<fieldset class="form-group"> <fieldset class="form-group">
<legend class="border-bottom mb-4"> <legend class="border-bottom mb-4">
Profil bearbeiten Profil bearbeiten
</legend> </legend>
<!-- FORMS LADEN --> <!-- FORMS LADEN -->
{{ profileform_form|crispy }} {{ profileform_form|crispy }}
<button type="button" id="" onclick="javascript:sendPassMail({{prof_user.pk}})" class="btn btn-success">E-Mail mit Link zur Passworterstellung senden</button>&nbsp;&nbsp;<span class="alert alert-success" id="mailsend" role="alert" style="display: none;">&nbsp;E-Mail gesendet!</span> <button type="button" id="" onclick="javascript:sendPassMail({{prof_user.pk}})" class="btn btn-success">E-Mail mit Link zur Passworterstellung senden</button>&nbsp;&nbsp;<span class="alert alert-success" id="mailsend" role="alert" style="display: none;">&nbsp;E-Mail gesendet!</span>
</fieldset> </fieldset>
@ -63,7 +66,7 @@
<option id="{{us.pk}}" value="{{us.first_name}} {{us.last_name}}"></option> <option id="{{us.pk}}" value="{{us.first_name}} {{us.last_name}}"></option>
{% endfor %} {% endfor %}
</datalist> </datalist>
</div> </div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
@ -73,6 +76,111 @@
</form> </form>
</div> </div>
</div> </div>
<!-- MODAL TO CROP THE IMAGE -->
<!-- MODAL TO CROP THE IMAGE -->
<div class="modal fade " id="modalCrop">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Bereich bestimmen</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" onclick="clearImgField()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="imgmodbody">
<img src="" id="imagemod" style="max-width: 100%; max-height: 100%;">
</div>
<div class="modal-footer">
<div class="btn-group pull-left" role="group">
<button type="button" class="btn btn-default js-zoom-in">
<span class="glyphicon glyphicon-zoom-in"></span>
</button>
<button type="button" class="btn btn-default js-zoom-out">
<span class="glyphicon glyphicon-zoom-out"></span>
</button>
</div>
<button type="button" class="btn btn-default" data-dismiss="modal" onclick="clearImgField()">Abbrechen</button>
<button type="button" class="btn btn-primary js-crop-and-upload">Ausschneiden</button>
</div>
</div>
</div>
</div>
{% block javascript %}
<script>
$("#id_x").val(0);
$("#id_y").val(0);
$("#id_width").val($("#profpic")[0]['naturalWidth']);
$("#id_height").val($("#profpic")[0]['naturalHeight']);
function clearImgField(){
$("#id_image").val("");
}
/* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */
$("#id_image").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$("#imagemod").attr("src", e.target.result);
$("#modalCrop").modal("show");
}
reader.readAsDataURL(this.files[0]);
}
});
var cropBoxData;
var canvasData;
var $image = $("#imagemod");
$("#modalCrop").on("shown.bs.modal", function () {
$image.cropper({
viewMode: 3,
aspectRatio: 1/1,
strict: false,
cropBoxMovable: true,
cropBoxResizable: true,
minCropBoxWidth: 200,
minCropBoxHeight: 200,
ready: function () {
$image.cropper("setCanvasData", canvasData);
$image.cropper("setCropBoxData", cropBoxData);
}
});
$("#imgmodbody").css({
"maxWidth": 465
});
}).on("hidden.bs.modal", function () {
cropBoxData = $image.cropper("getCropBoxData");
canvasData = $image.cropper("getCanvasData");
$image.cropper("destroy");
});
$(".js-zoom-in").click(function () {
$image.cropper("zoom", 0.1);
});
$(".js-zoom-out").click(function () {
$image.cropper("zoom", -0.1);
});
/* SCRIPT TO COLLECT THE DATA AND POST TO THE SERVER */
$(".js-crop-and-upload").click(function () {
var cropData = $image.cropper("getData");
$("#id_x").val(cropData["x"]);
$("#id_y").val(cropData["y"]);
$("#id_height").val(cropData["height"]);
$("#id_width").val(cropData["width"]);
$("#id_image").attr("src", $image);
$("#modalCrop").modal('toggle');
});
</script>
{% endblock %}
<script type="text/javascript"> <script type="text/javascript">
var ua = window.navigator.userAgent; var ua = window.navigator.userAgent;
var isIE = /MSIE|Trident/.test(ua); var isIE = /MSIE|Trident/.test(ua);

View File

@ -6,6 +6,8 @@ from .models import Profile, Agency
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from areas.models import Areas from areas.models import Areas
from tasks.models import Tasks from tasks.models import Tasks
from PIL import Image
# Standard-User-Formular - NUR Username und Password wird hier genutzt # Standard-User-Formular - NUR Username und Password wird hier genutzt
class UsersAddNewUser(UserCreationForm): class UsersAddNewUser(UserCreationForm):
@ -25,9 +27,13 @@ class UsersChangeProfil(forms.ModelForm):
# Formular zum hinzufügen neuer Agentur-Mitglieder # Formular zum hinzufügen neuer Agentur-Mitglieder
class UsersAddProfileForm(forms.ModelForm): class UsersAddProfileForm(forms.ModelForm):
x = forms.FloatField(widget=forms.HiddenInput())
y = forms.FloatField(widget=forms.HiddenInput())
width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput())
class Meta: class Meta:
model = Profile model = Profile
labels = { labels = {
"phoneland" : "Telefon", "phoneland" : "Telefon",
"phonemobile" : "Mobil", "phonemobile" : "Mobil",
@ -36,7 +42,23 @@ class UsersAddProfileForm(forms.ModelForm):
"image" : "Profilbild", "image" : "Profilbild",
"visible" : "Im Organigramm sichtbar" "visible" : "Im Organigramm sichtbar"
} }
fields = ['phoneland','phonemobile', 'visible', 'func', 'compfunc', 'image']
fields = ['phoneland','phonemobile', 'visible', 'func', 'compfunc', 'image', 'x', 'y', 'width', 'height']
def save(self):
photo = super(UsersAddProfileForm, self).save()
try:
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(photo.image)
cropped_image = image.crop((x, y, w+x, h+y))
resized_image = cropped_image.resize((560, 560), Image.ANTIALIAS)
resized_image.save(photo.image.path)
return photo
except:
print("no photo")
# Formular zum hinzufügen neuer Agentur-Mitglieder # Formular zum hinzufügen neuer Agentur-Mitglieder
class AgencyUpdateForm(forms.ModelForm): class AgencyUpdateForm(forms.ModelForm):

View File

@ -24,7 +24,7 @@ from PIL import Image
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.forms import PasswordResetForm
from django.template.loader import render_to_string from django.template.loader import render_to_string
from io import StringIO
''' '''
DASHBOARD-View DASHBOARD-View
@ -201,9 +201,6 @@ class UsersPermUpdateView(LoginRequiredMixin, View):
messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!') messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!')
return HttpResponseRedirect('/dashboard/usersman/') return HttpResponseRedirect('/dashboard/usersman/')
# Benutzerprofil wird aktualisiert # Benutzerprofil wird aktualisiert
@login_required @login_required
def ProfileUpdateView(request, pk): def ProfileUpdateView(request, pk):
@ -212,20 +209,20 @@ def ProfileUpdateView(request, pk):
if request.method == 'POST': if request.method == 'POST':
profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile) profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile)
#profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user) #profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user)
prename = prof_user.first_name
name = prof_user.last_name
if profileform_form.is_valid(): if profileform_form.is_valid():
profileform_form.save() profileform_form.save()
prename = prof_user.first_name messages.success(request, f'Daten für {prename} {name} aktualisiert!')
name = prof_user.last_name
messages.success(request, f'Daten für {prename} {name} aktualisiert!')
# Daten neu laden und nicht die "Mächten sie die Daten speichern...?"
return redirect('users-management') return redirect('users-management')
else: else:
# Form in Klammern sind die aktuellen Daten :) # Form in Klammern sind die aktuellen Daten :)
profileform_form = UsersAddProfileForm(instance=prof_user.profile) profileform_form = UsersAddProfileForm(instance=prof_user.profile)
possible_users = User.objects.filter(profile__agency__pk=prof_user.profile.agency.pk)
# Nur User, die im Organigramm auch sichtbar sein, können ausgewählt werden
possible_users = User.objects.filter(profile__agency__pk=prof_user.profile.agency.pk).filter(profile__visible=True)
context = { context = {
'prof_user' : prof_user, 'prof_user' : prof_user,