Commit 3273cbff authored by Sylvain Coulange's avatar Sylvain Coulange
Browse files

mise à jour player editeur

parent bb6523e7
from django.contrib import admin
from .models import Serie, Mot, Audio, Image
from .models import Serie, Audio, Image
# TUTO : https://www.youtube.com/watch?v=g5DTIiFAiSk
admin.site.site_header = 'Tableau de bord du PhonoGraphe'
......@@ -15,6 +15,5 @@ class SerieAdmin(admin.ModelAdmin):
# Register your models here.
admin.site.register(Serie, SerieAdmin)
admin.site.register(Mot)
admin.site.register(Audio)
admin.site.register(Image)
\ No newline at end of file
......@@ -9,54 +9,64 @@ class Serie(models.Model):
code = models.CharField(default='nouvelle_serie', max_length=100)
description = models.TextField(blank=True, max_length=500)
auteur = models.ForeignKey(User, on_delete=models.PROTECT)
panneau = models.CharField(default='phonoFrDo', max_length=50)
fidel = models.CharField(default='fidelDo', max_length=50)
typeActivite = models.CharField(default='phonologique', max_length=50) # phonologique / phonographique /...
droitsModif = models.TextField(default='[]') # liste des users ayant droit de modification autres que l'auteur
audioDeb = models.CharField(default='0', max_length=1)
imageDeb = models.CharField(default='0', max_length=1)
videoDeb = models.CharField(default='0', max_length=1)
graphieDeb = models.CharField(default='0', max_length=1)
audioFin = models.CharField(default='0', max_length=1)
imageFin = models.CharField(default='0', max_length=1)
videoFin = models.CharField(default='0', max_length=1)
graphieFin = models.CharField(default='0', max_length=1)
phonoFin = models.CharField(default='0', max_length=1)
audioFin = models.CharField(default='0', max_length=1)
videoDeb = models.CharField(default='0', max_length=1)
syntheseVocale = models.CharField(default='0', max_length=1)
panneauPartiel = models.CharField(default='0', max_length=1)
phonVisibles = models.TextField(default='[]')
mots = models.TextField(default='[]')
class Mot(models.Model):
auteur = models.CharField(max_length=100) # models.ForeignKey(User, on_delete=models.PROTECT)
dateCreation = models.DateTimeField(auto_now_add=True, auto_now=False)
dateModification = models.DateTimeField(auto_now_add=False, auto_now=True)
motGenerique = models.CharField(max_length=100) # "chat"
phono = models.CharField(max_length=1000) # Liste des phonos choisies [["phon_s_maj","phon_a"]]
audio = models.FileField(blank=True, upload_to='playerPhono/audio/')
image = models.ImageField(blank=True, upload_to='playerPhono/im/')
class Audio(models.Model):
nom = models.CharField(max_length=255)
description = models.TextField(blank=True)
upload_by = models.ForeignKey(User, on_delete=models.PROTECT)
upload_at = models.DateTimeField(auto_now_add=True)
source = models.CharField(max_length=500, blank=True)
used_by = models.TextField(default="[]") # Liste des codes de séries qui utilisent ce média
file = models.FileField(upload_to="audio-uploads/")
def __str__(self):
return self.motGenerique
# def save(self, *args, **kwargs):
# super().save(*args, **kwargs)
# img = Image.open(self.image.path)
# if img.height > 300 or img.width > 300:
# output_size = (300, 300)
# img.thumbnail(output_size)
# img.save(self.image.path)
return self.nom
class Audio(models.Model):
nom = models.CharField(max_length=255, blank=True)
auteur = models.CharField(max_length=255, blank=True)
file = models.FileField(upload_to="audio-uploads/")
class Video(models.Model):
nom = models.CharField(max_length=255)
description = models.TextField(blank=True)
upload_by = models.ForeignKey(User, on_delete=models.PROTECT)
upload_at = models.DateTimeField(auto_now_add=True)
source = models.CharField(max_length=500, blank=True)
used_by = models.TextField(default="[]") # Liste des codes de séries qui utilisent ce média
file = models.FileField(upload_to="video-uploads/")
def __str__(self):
return self.nom
class Image(models.Model):
nom = models.CharField(max_length=255, blank=True)
auteur = models.CharField(max_length=255, blank=True)
file = models.ImageField(upload_to="image-uploads/")
nom = models.CharField(max_length=255)
description = models.TextField(blank=True)
upload_by = models.ForeignKey(User, on_delete=models.PROTECT)
upload_at = models.DateTimeField(auto_now_add=True)
source = models.CharField(max_length=500, blank=True)
used_by = models.TextField(default="[]") # Liste des codes de séries qui utilisent ce média
file = models.FileField(upload_to="audio-uploads/")
def __str__(self):
return self.nom
......@@ -69,4 +79,26 @@ class Image(models.Model):
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.file.path)
\ No newline at end of file
img.save(self.file.path)
# Stucture Mot :
{
"motGenerique": "ponte",
"phono": [
["phon_p", "phon_o_maj_nas", "phon_t"]
],
"audioDeb" : "filename.ext",
"imageDeb" : "filename.ext",
"videoDeb" : "filename.ext",
"graphieDeb" : "text",
"audioFin" : "filename.ext",
"imageFin" : "filename.ext",
"videoFin" : "filename.ext",
"graphieFin" : "text",
"phonographies": [
[["phon_f","f"],["phon_u","ou"],["phon_r_maj","r"],["phon_s_maj","ch"],["phon_e_maj","e"],["phon_t","tte"]]
]
}
\ No newline at end of file
......@@ -106,28 +106,83 @@ def save2db(request):
def openPlayerHome(request):
updateTimeStr = updateTime()
series = Serie.objects.all()
return render(request, 'playerHome.html', {'updateTime': updateTimeStr, 'series': series, 'titrePage': 'phonoplayer'})
# Réécriture de openPlayerHome en ListView
class SerieListView(ListView):
model = Serie
template_name = 'playerHome.html'
context_object_name = 'series'
#ordering = ['-dateCreation']
class SerieDetailView(DetailView):
model = Serie
template_name = 'playerSeriePage.html'
return render(request, 'playerHome.html', {'updateTime': updateTimeStr, 'titrePage': 'phonoplayer'})
def getSeries(request):
series = Serie.objects.all()
seriesMainInfo = []
for s in series:
seriesMainInfo.append({
"code":s.code,
"nom":s.nom,
"auteurIm":s.auteur.profile.image.url,
"auteur":s.auteur.username,
"description":s.description,
"dateCreation":s.dateCreation.strftime("%Y/%m/%d"),
"dateModification":s.dateModification.strftime("%Y/%m/%d %H:%M")
})
return JsonResponse({ "series":seriesMainInfo })
def infoSerie(request, pk):
s = Serie.objects.filter(code=pk).first()
serie = {
"nom":s.nom,
"dateCreation": s.dateCreation.strftime("%Y-%m-%d %H:%M:%S"),
"dateModification": s.dateModification.strftime("%Y-%m-%d %H:%M:%S"),
"code": s.code,
"description": s.description,
"auteur": s.auteur.username,
"auteurIm": s.auteur.profile.image.url,
"audioDeb": s.audioDeb,
"imageDeb": s.imageDeb,
"videoDeb": s.videoDeb,
"graphieDeb": s.graphieDeb,
"audioFin": s.audioFin,
"imageFin": s.imageFin,
"videoFin": s.videoFin,
"graphieFin": s.graphieFin,
"phonoFin": s.phonoFin,
"syntheseVocale": s.syntheseVocale,
"panneauPartiel": s.panneauPartiel,
"phonVisibles": s.phonVisibles,
"mots": s.mots
}
return JsonResponse({ "serieInfo":serie })
def openPlayerPhono(request, pk):
updateTimeStr = updateTime()
serieContent = Serie.objects.filter(code=pk).first()
print(serieContent)
print("Demande ouverture série", serieContent.nom, ' (', pk, ')')
return render(request, 'playerPhono.html', {'updateTime': updateTimeStr, 'serieContent':serieContent, 'titrePage': 'phonoplayer'})
s = Serie.objects.filter(code=pk).first()
serie = {
"nom":s.nom,
"dateCreation": s.dateCreation.strftime("%Y-%m-%d %H:%M:%S"),
"dateModification": s.dateModification.strftime("%Y-%m-%d %H:%M:%S"),
"code": s.code,
"description": s.description,
"auteur": s.auteur.username,
"audioDeb": s.audioDeb,
"imageDeb": s.imageDeb,
"videoDeb": s.videoDeb,
"graphieDeb": s.graphieDeb,
"audioFin": s.audioFin,
"imageFin": s.imageFin,
"videoFin": s.videoFin,
"graphieFin": s.graphieFin,
"phonoFin": s.phonoFin,
"syntheseVocale": s.syntheseVocale,
"panneauPartiel": s.panneauPartiel,
"phonVisibles": s.phonVisibles,
"mots": s.mots
}
print(serie)
print("Demande ouverture série", serie["nom"], ' (', serie["code"], ')')
return render(request, 'playerPhono.html', {'updateTime': updateTimeStr, "serie": serie, "serieJson": json.dumps(serie), 'titrePage': 'phonoplayer'})
def playIpa(request):
......
......@@ -37,7 +37,9 @@ urlpatterns = [
path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name="registration/password_reset_confirm.html"), name='password_reset_confirm'),
path('reset_password_complete/', auth_views.PasswordResetCompleteView.as_view(template_name="registration/password_reset_complete.html"), name='password_reset_complete'),
path('player/createSerie/', user_views.createSerie, name='createSerie'),
path('player/createSerie/', user_views.editSerie, name='createSerie'),
path('player/listMediaFiles/', csrf_exempt(user_views.listMediaFiles), name='listeMediaFiles'),
path('player/saveSerie/', csrf_exempt(user_views.saveSerie), name='saveSerie'),
path('player/uploadAudio/', user_views.uploadAudio, name='uploadAudio'),
path('player/uploadImage/', user_views.uploadImage, name='uploadImage'),
......@@ -49,10 +51,14 @@ urlpatterns = [
path('<str:pageLang>/id-<str:pageId>/', clavier_views.loadPage),
path('export/', csrf_exempt(clavier_views.save2db)),
path('player/', clavier_views.openPlayerHome, name='home'), # ou SerieListView.as_view()
path('player/serie-<str:pk>', clavier_views.SerieDetailView.as_view(), name='serie-page'),
path('player/', clavier_views.openPlayerHome, name='home'),
path('player/getSeries/', csrf_exempt(clavier_views.getSeries), name='getSeries'),
#path('player/serie-<str:pk>', clavier_views.SerieDetailView.as_view(), name='serie-page'),
path('player/serie-<str:pk>/info', clavier_views.infoSerie, name='serie-info'),
path('player/serie-<str:pk>/play', clavier_views.openPlayerPhono, name='serie-play'),
path('player/serie-<str:pk>/edit', user_views.editSerie, name='serie-edit'),
path('_delSerie/', csrf_exempt(user_views.delSerie)),
path('_saveTrace/', csrf_exempt(user_views.saveTrace)),
path('_playIpa/', csrf_exempt(clavier_views.playIpa)),
......
MDB5
Version: FREE 3.4.0
Documentation:
https://mdbootstrap.com/docs/standard/
Contact:
office@mdbootstrap.com
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Material Design for Bootstrap</title>
<!-- MDB icon -->
<link rel="icon" href="img/mdb-favicon.ico" type="image/x-icon" />
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.2/css/all.css" />
<!-- Google Fonts Roboto -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
/>
<!-- MDB -->
<link rel="stylesheet" href="css/mdb.min.css" />
</head>
<body>
<!-- Start your project here-->
<div class="container">
<div class="d-flex justify-content-center align-items-center" style="height: 100vh;">
<div class="text-center">
<img
class="mb-4"
src="https://mdbootstrap.com/img/logo/mdb-transparent-250px.png"
style="width: 250px; height: 90px;"
/>
<h5 class="mb-3">Thank you for using our product. We're glad you're with us.</h5>
<p class="mb-3">MDB Team</p>
<a
class="btn btn-primary btn-lg"
href="https://mdbootstrap.com/docs/standard/getting-started/"
target="_blank"
role="button"
>Start MDB tutorial</a
>
</div>
</div>
</div>
<!-- End your project here-->
<!-- MDB -->
<script type="text/javascript" src="js/mdb.min.js"></script>
<!-- Custom scripts -->
<script type="text/javascript"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
/*!
* Bootstrap alert.js v5.0.0-beta2 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory(
require('./dom/data.js'),
require('./dom/event-handler.js'),
require('./base-component.js')
))
: typeof define === 'function' && define.amd
? define(['./dom/data', './dom/event-handler', './base-component'], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Alert = factory(global.Data, global.EventHandler, global.Base)));
})(this, function (Data, EventHandler, BaseComponent) {
'use strict';
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.0.0-beta2): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
var MILLISECONDS_MULTIPLIER = 1000;
var TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
var getSelector = function getSelector(element) {
var selector = element.getAttribute('data-bs-target');
if (!selector || selector === '#') {
var hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
// so everything starting with `#` or `.`. If a "real" URL is used as the selector,
// `document.querySelector` will rightfully complain it is invalid.
// See https://github.com/twbs/bootstrap/issues/32273
if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
return null;
} // Just in case some CMS puts out a full URL with the anchor appended
if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
hrefAttr = '#' + hrefAttr.split('#')[1];
}
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
}
return selector;
};
var getElementFromSelector = function getElementFromSelector(element) {
var selector = getSelector(element);
return selector ? document.querySelector(selector) : null;
};
var getTransitionDurationFromElement = function getTransitionDurationFromElement(element) {
if (!element) {
return 0;
} // Get transition-duration of the element
var _window$getComputedSt = window.getComputedStyle(element),
transitionDuration = _window$getComputedSt.transitionDuration,
transitionDelay = _window$getComputedSt.transitionDelay;
var floatTransitionDuration = Number.parseFloat(transitionDuration);
var floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
} // If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (
(Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) *
MILLISECONDS_MULTIPLIER
);
};
var triggerTransitionEnd = function triggerTransitionEnd(element) {
element.dispatchEvent(new Event(TRANSITION_END));
};
var emulateTransitionEnd = function emulateTransitionEnd(element, duration) {
var called = false;
var durationPadding = 5;
var emulatedDuration = duration + durationPadding;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
}
element.addEventListener(TRANSITION_END, listener);
setTimeout(function () {
if (!called) {
triggerTransitionEnd(element);
}
}, emulatedDuration);
};
var getjQuery = function getjQuery() {
var _window = window,
jQuery = _window.jQuery;
if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return jQuery;
}
return null;
};
var onDOMContentLoaded = function onDOMContentLoaded(callback) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', callback);
} else {
callback();
}
};
document.documentElement.dir === 'rtl';
var defineJQueryPlugin = function defineJQueryPlugin(name, plugin) {
onDOMContentLoaded(function () {
var $ = getjQuery();
/* istanbul ignore if */
if ($) {
var JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = function () {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
var NAME = 'alert';
var DATA_KEY = 'bs.alert';
var EVENT_KEY = '.' + DATA_KEY;
var DATA_API_KEY = '.data-api';
var SELECTOR_DISMISS = '[data-bs-dismiss="alert"]';
var EVENT_CLOSE = 'close' + EVENT_KEY;
var EVENT_CLOSED = 'closed' + EVENT_KEY;
var EVENT_CLICK_DATA_API = 'click' + EVENT_KEY + DATA_API_KEY;
var CLASS_NAME_ALERT = 'alert';
var CLASS_NAME_FADE = 'fade';
var CLASS_NAME_SHOW = 'show';
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
var Alert = /*#__PURE__*/ (function (_BaseComponent) {
_inheritsLoose(Alert, _BaseComponent);
function Alert() {
return _BaseComponent.apply(this, arguments) || this;
}
var _proto = Alert.prototype;
// Public
_proto.close = function close(element) {
var rootElement = element ? this._getRootElement(element) : this._element;
var customEvent = this._triggerCloseEvent(rootElement);
if (customEvent === null || customEvent.defaultPrevented) {
return;
}
this._removeElement(rootElement);
}; // Private
_proto._getRootElement = function _getRootElement(element) {
return getElementFromSelector(element) || element.closest('.' + CLASS_NAME_ALERT);
};
_proto._triggerCloseEvent = function _triggerCloseEvent(element) {