omassot před 7 roky
rodič
revize
4769955d57

+ 2 - 1
.gitignore

@@ -8,4 +8,5 @@
 tmp*
 ~$*
 .sqlite3
-main/migrations/*
+main/migrations/*
+main/media/upload/*

+ 13 - 1
backlog/settings.py

@@ -127,10 +127,14 @@ LOGIN_REDIRECT_URL = '/'
 STATIC_URL = '/static/'
 STATIC_ROOT = os.path.join(BASE_DIR, 'main/static/')
 
+MEDIA_URL = '/media/'
+MEDIA_ROOT = os.path.join(BASE_DIR, 'main/media/')
+
+
 DJANGO_NOTIFICATIONS_CONFIG = { 'USE_JSONFIELD': True}
 
 MARTOR_ENABLE_CONFIGS = {
-    'imgur': 'false',     # to enable/disable imgur/custom uploader.
+    'imgur': 'true',     # to enable/disable imgur/custom uploader.
     'mention': 'false',  # to enable/disable mention
     'jquery': 'true',    # to include/revoke jquery (require for admin default django)
     'living': 'false',   # to enable/disable live updates in preview
@@ -140,6 +144,12 @@ MARTOR_MARKDOWN_SAFE_MODE = True # default
 
 MARTOR_ENABLE_LABEL = True
 
+import time
+MARTOR_UPLOAD_PATH = 'upload/images/{}'.format(time.strftime("%Y/%m/%d/"))
+MARTOR_UPLOAD_URL = '/upload/'
+
+MAX_IMAGE_UPLOAD_SIZE = 20971520  # 20MB
+
 MARTOR_MARKDOWN_EXTENSIONS = [
     'markdown.extensions.extra',
     'markdown.extensions.nl2br',
@@ -157,3 +167,5 @@ MARTOR_MARKDOWN_EXTENSIONS = [
 # Markdown Extensions Configs
 MARTOR_MARKDOWN_EXTENSION_CONFIGS = {}
 
+
+

+ 1 - 0
main/media/readme.md

@@ -0,0 +1 @@
+Media storage

+ 7 - 1
main/static/css/custom.css

@@ -59,7 +59,13 @@ a.anchor {
     visibility: hidden;
 }
 
-@media screen and (max-width: 1400px) {
+@media screen and (max-width: 1550px) {
+	.hide-on-medium-screen {
+		display: none;
+	}
+}
+
+@media screen and (max-width: 1300px) {
 	.hide-on-small-screen {
 		display: none;
 	}

+ 3 - 4
main/templates/_layout.html

@@ -68,7 +68,6 @@
 	        				<i class="fa fa-bell"></i><span class="notif-count">{{ notif_unread_count }}</span> <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i>
 	        			</a>
 	        		
-	        			
 						<div id="notif-dropdown" class="dropdown-content">
 						
 						{% if notif_unread_count > 0 %}
@@ -97,15 +96,15 @@
 					</div>
 	        		
 	        		<a class="tool-btn" href="{% url 'story_create' %}" style="margin-right: 1em;" title="Nouvelle Story">
-	        			<i class="fa fa-plus" style="color:#4183c4;"></i><span class="hide-on-small-screen"> Nouvelle Story</span>
+	        			<i class="fa fa-plus" style="color:#4183c4;"></i><span class="hide-on-medium-screen"> Nouvelle Story</span>
 	        		</a>
 	        		
 	        		<a class="tool-btn" href="{% url 'story_index' %}?assignee={{ request.user.id }}" style="margin-right: 1em;" title="Mes Stories">
-	        			<i class="fa fa-check-square-o" style="color:#4183c4;"></i><span class="hide-on-small-screen"> Mes Stories</span>
+	        			<i class="fa fa-check-square-o" style="color:#4183c4;"></i><span class="hide-on-medium-screen"> Mes Stories</span>
 	        		</a>
 	        		
 	        		<div id="user-panel" class="dropdown">
-	        			<a href="" id="user-show-btn"><i class="fa fa-user"></i><span class="hide-on-small-screen"> {{ request.user.first_name }} {{ request.user.last_name }}</span> <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i></a>
+	        			<a href="" id="user-show-btn"><i class="fa fa-user"></i><span class="hide-on-medium-screen"> {{ request.user.first_name }} {{ request.user.last_name }}</span> <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i></a>
 	        		
 						<div id="user-dropdown" class="dropdown-content">
 							<a href="{% url 'profile_update' %}">Mise à jour du profil</a>

+ 7 - 2
main/urls.py

@@ -4,11 +4,15 @@
 '''
 
 from django.urls import path
+from django.conf.urls.static import static
+
+from backlog import settings
 
 from . import views
 
 
 urlpatterns = [
+    
     path('', views.index, name='index'),
     path('register/', views.register, name='register'),
     path('profile_update/', views.profile_update, name='profile_update'),
@@ -43,5 +47,6 @@ urlpatterns = [
     path('search/', views.search, name='search'),
     path('notif/seen/<int:notif_id>/', views.notif_seen, name='notif_seen'),
     path('notif/allseen/', views.notif_all_seen, name='notif_all_seen'),
-    
-]
+    path('upload/', views.md_upload_file, name='md_upload_file'),
+
+] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ 34 - 0
main/views.py

@@ -1,17 +1,24 @@
 from datetime import datetime, timedelta
+import json
+import uuid
 
 from django.contrib.auth import logout, login, update_session_auth_hash
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.forms import PasswordChangeForm
 from django.contrib.auth.models import User
+from django.core.files.base import ContentFile
+from django.core.files.storage import default_storage
 from django.core.paginator import Paginator
 from django.db.models.aggregates import Sum
 from django.http.response import HttpResponse
 from django.shortcuts import render, get_object_or_404, redirect
 from django.urls.base import reverse
+from martor.utils import LazyEncoder
 from notifications.models import Notification
 from notifications.signals import notify
+from path import Path
 
+from backlog import settings
 from main.forms import StoryForm, EpicForm, RegisterForm, ProfileForm, \
     CommentForm, SprintForm, NewSprintForm
 from main.models import Story, Epic, Sprint, Comment, Project
@@ -475,3 +482,30 @@ def notify_sprint_end(sprint, next_sprint, ended_by):
     target_url = reverse(f"report_sprints")
     notify.send(ended_by, recipient=User.objects.all(), action_object = sprint, verb=f"Fin du <a href='{target_url}'>{sprint}</a>")
     notify.send(ended_by, recipient=User.objects.all(), action_object = sprint, verb=f"Démarrage du <a href='{target_url}'>{next_sprint}</a>")
+
+
+
+@login_required
+def md_upload_file(request):
+    if request.method == 'POST' and request.is_ajax():
+        if 'markdown-image-upload' in request.FILES:
+            
+            image = request.FILES['markdown-image-upload']
+            
+            if image.size > settings.MAX_IMAGE_UPLOAD_SIZE:
+                data = json.dumps({'status': 405, 
+                                   'error': _('Maximum image file is %(size) MB.') % {'size': (settings.MAX_IMAGE_UPLOAD_SIZE / (1024 * 1024))} }, 
+                                   cls=LazyEncoder)
+                return HttpResponse(data, content_type='application/json', status=405)
+
+            img_uuid = "{0}-{1}".format(uuid.uuid4().hex[:10], image.name.replace(' ', '-'))
+            tmp_file = Path(settings.MARTOR_UPLOAD_PATH) / img_uuid
+            def_path = default_storage.save(tmp_file, ContentFile(image.read()))
+            img_url = Path(settings.MEDIA_URL) / def_path
+
+            data = json.dumps({'status': 200, 'link': img_url, 'name': image.name})
+            return HttpResponse(data, content_type='application/json')
+        return HttpResponse(_('Invalid request!'))
+    return HttpResponse(_('Invalid request!'))
+
+