Error in displaying chart in Django with chartit - javascript

I have an application for which I am trying to display a simple chart of number of proposals per country. I am using pivotchart in chartit as explained here
I have a model like this
class Proposal(models.Model):
org = models.CharField(max_length=200)
country = models.CharField(max_length=100)
recdate = models.DateField(blank=False)
subdate = models.DateField(blank=False)
status = models.CharField(choices = stat_val, max_length=20)
and as explained in the chartit GitHub, I have added this to views
from django.db.models import Count
from chartit import PivotDataPool, PivotChart
from django.shortcuts import render_to_response
def proposal_pivot_chart_view(request):
# Step 1: Create a PivotDataPool with the data we want to retrieve.
proposalpivotdata = PivotDataPool(
series=[{
'options': {
'source': Proposal.objects.all(),
'categories': ['country'],
},
'terms': {
'countprop': Count('id'),
}
}]
)
# Step 2: Create the PivotChart object
chart1 = PivotChart(
datasource=proposalpivotdata,
series_options=[{
'options': {
'type': 'column',
'stacking': True
},
'terms': ['countprop']
}],
chart_options={
'title': {
'text': 'Proposals by Countries'
},
'xAxis': {
'title': {
'text': 'Country'
}
}
}
)
# Step 3: Send the PivotChart object to the template.
return render_to_response({'chart1': chart1})
and I have created a template like this
<!DOCTYPE html>
<html>
<head>
{% load staticfiles %}
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}" >
<link rel="stylesheet" href="{% static 'bootstrap/css/light-bootstrap-dashboard.css' %}" >
<link rel="stylesheet" href="{% static 'bootstrap/css/animate.min.css' %}">
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link href='http://fonts.googleapis.com/css?family=Roboto:400,700,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="{% static 'bootstrap/css/pe-icon-7-stroke.css' %}">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<script src="{{ MEDIA_URL }}highcharts/js/highcharts.js" type="text/javascript"></script>
{% load chartit %}
{{ rainpivchart|load_charts:"container" }}
</head>
<body>
{% include "proposal/main-banner.html"%}
<div id='container'></div>
<button>Back to Proposal List</button>
</body>
</html>
But there is some problem and I am getting error
TemplateDoesNotExist at /chart1/
{'chart1': <chartit.charts.PivotChart object at 0x046ADF30>}
Request Method:
GET
Request URL:
http://127.0.0.1:8000/chart1/
Django Version:
1.10.6
Exception Type:
TemplateDoesNotExist
Exception Value:
{'chart1': <chartit.charts.PivotChart object at 0x046ADF30>}
Exception Location:
C:\Users\Parag\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django-1.10.6-py3.6.egg\django\template\loader.py in get_template, line 25
Python Executable:
C:\Users\Parag\AppData\Local\Programs\Python\Python36-32\python.exe
Python Version:
3.6.0
Python Path:
['C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\Lib\\site-packages\\Django-1.10.6-py3.6.egg\\django\\bin\\myoffice',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\python36.zip',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\DLLs',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\lib',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages',
'C:\\Users\\Parag\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages\\django-1.10.6-py3.6.egg']
Server time:
Tue, 18 Apr 2017 16:09:08 +0400
Template-loader postmortem
Django tried loading these templates, in this order:
Using engine django:
django.template.loaders.app_directories.Loader: C:\Users\Parag\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django-1.10.6-py3.6.egg\django\contrib\admin\templates\{'chart1': <chartit.charts.PivotChart object at 0x046ADF30>} (Source does not exist)
django.template.loaders.app_directories.Loader: C:\Users\Parag\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django-1.10.6-py3.6.egg\django\contrib\auth\templates\{'chart1': <chartit.charts.PivotChart object at 0x046ADF30>} (Source does not exist)
django.template.loaders.app_directories.Loader: C:\Users\Parag\AppData\Local\Programs\Python\Python36-32\lib\site-packages\highcharts\templates\{'chart1': <chartit.charts.PivotChart object at 0x046ADF30>} (Source does not exist)

Related

Extract features from blob with Librosa

I am trying to record a voice message in the frontend and send it to the Django backend to test it against a ML algorithm of voice gender recognition. In the frontend I record the voice using videojs-record and I use AJAX to send the blob to the backend like so:
{% extends 'base.html' %}
{% load static %}
{% block title %}Voice Detector{% endblock %}
{% block extracss %}
<link href="{% static 'css/voice_detector.css' %}" rel="stylesheet" />
<link href="{% static 'css/video-js.css' %}" rel="stylesheet" />
<link href="{% static 'css/all.min.css' %}" rel="stylesheet" />
<link href="{% static 'css/videojs.wavesurfer.min.css' %}" rel="stylesheet" />
<link href="{% static 'css/videojs.record.css' %}" rel="stylesheet" />
{% endblock %}
{% block content %}
<div class="banner">
<div class="max-width">
<div class="banner-content">
<p class="motto">Test your voice right now!</p>
<p class="description">
Register your voice while reading the text below and our program will
detect your gender in a few seconds!
</p>
</div>
</div>
</div>
<div class="details">
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-offset-4 is-4">
<h1 class="title">Record audio</h1>
<article class="message is-success" id="alert">
<div class="message-header">
<p>Recorded successfully!</p>
<button class="delete" aria-label="delete"></button>
</div>
<div class="message-body">
You have successfully recorded your message. You can now click on
the Submit button to post it.
</div>
</article>
<div class="field">
<div
class="control has-icons-left has-icons-right"
style="margin-top: 1rem"
>
<audio
id="recordAudio"
class="video-js vjs-default-skin"
></audio>
</div>
<div class="control" style="margin-top: 1rem">
<button class="home-btn" id="submit" disabled>Submit</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{% endblock %}
{% block extrajs %}
<script src="{% static 'js/video.min.js' %}"></script>
<script src="{% static 'js/RecordRTC.js' %}"></script>
<script src="{% static 'js/adapter-latest.js' %}"></script>
<script src="{% static 'js/wavesurfer.js' %}"></script>
<script src="{% static 'js/wavesurfer.microphone.min.js' %}"></script>
<script src="{% static 'js/videojs.wavesurfer.min.js' %}"></script>
<script src="{% static 'js/videojs.record.min.js' %}"></script>
<script src="{% static 'js/browser-workaround.js' %}"></script>
<script>
// First lets hide the message
document.getElementById("alert").style.display = "none";
// Next, declare the options that will passed into the recording constructor
const options = {
controls: true,
bigPlayButton: false,
width: 600,
height: 300,
fluid: true, // this ensures that it's responsive
plugins: {
wavesurfer: {
backend: "WebAudio",
waveColor: "#f7fff7", // change the wave color here. Background color was set in the css above
progressColor: "#ffe66d",
displayMilliseconds: true,
debug: true,
cursorWidth: 1,
hideScrollbar: true,
plugins: [
// enable microphone plugin
WaveSurfer.microphone.create({
bufferSize: 4096,
numberOfInputChannels: 1,
numberOfOutputChannels: 1,
constraints: {
video: false,
audio: true,
},
}),
],
},
record: {
audio: true, // only audio is turned on
video: false, // you can turn this on as well if you prefer video recording.
maxLength: 180, // how long do you want the recording?
displayMilliseconds: true,
debug: true,
},
},
};
// apply audio workarounds for certain browsers
applyAudioWorkaround();
// create player and pass the the audio id we created then
var player = videojs("recordAudio", options, function () {
// print version information at startup
var msg =
"Using video.js " +
videojs.VERSION +
" with videojs-record " +
videojs.getPluginVersion("record") +
", videojs-wavesurfer " +
videojs.getPluginVersion("wavesurfer") +
", wavesurfer.js " +
WaveSurfer.VERSION +
" and recordrtc " +
RecordRTC.version;
videojs.log(msg);
});
// error handling
player.on("deviceError", function () {
console.log("device error:", player.deviceErrorCode);
});
player.on("error", function (element, error) {
console.error(error);
});
// user clicked the record button and started recording
player.on("startRecord", function () {
console.log("started recording!");
$("#submit").prop("disabled", true);
});
// user completed recording and stream is available
player.on("finishRecord", function () {
const audioFile = player.recordedData;
console.log("finished recording: ", audioFile);
$("#submit").prop("disabled", false);
document.getElementById("alert").style.display = "block";
});
// Give event listener to the submit button
$("#submit").on("click", function (event) {
event.preventDefault();
let btn = $(this);
// change the button text and disable it
btn.html("Submitting...").prop("disabled", true).addClass("disable-btn");
// create a new File with the recordedData and its name
const recordedFile = new File([player.recordedData], `test.wav`);
// initializes an empty FormData
let data = new FormData();
// appends the recorded file and language value
data.append("file", recordedFile);
// post url endpoint
$.ajax({
url: "{% url 'detector' %}",
method: "POST",
data: data,
dataType: "json",
success: function (response) {
if (response.success) {
document.getElementById("alert").style.display = "block";
window.location.href = `${response.url}`;
} else {
btn.html("Error").prop("disabled", false);
}
},
error: function (error) {
console.error(error);
},
cache: false,
processData: false,
contentType: false,
});
});
</script>
{% endblock %}
On the backend I try to use wave to save the file as a valid .wav, like so:
def post(self, request):
f = request.FILES['file']
with open('file.wav', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
with open('file.wav', 'rb') as file:
file_content = file.read()
audio = wave.open('test.wav', 'wb')
audio.setnchannels(1)
audio.setnframes(1)
audio.setsampwidth(1)
audio.setframerate(8000)
audio.writeframes(file_content)
audio.close()
(prediction, probability) = predict('test.wav')
context["prediction"] = prediction
context["probability"] = probability*100
os.remove(file_name)
return render(request, self.template_name, context=context)
Here, I tried 2 things. The first try was to save the blob directly into a file using open with 'wb'. The problem with this is approach is that librosa complains that the file type is not recognized. The other try was with wave, but whatever I try, the file saved with wave results in noise and the prediction algorithm fails. Here is how I would like to use the file with the recorded voice to make the prediction:
def predict(file_name):
# construct the model
model = create_model()
# load the saved/trained weights
model.load_weights('model.h5')
# extract features and reshape it
features = extract_feature(file_name, mel=True).reshape(1, -1)
# predict the gender!
male_prob = model.predict(features)[0][0]
female_prob = 1 - male_prob
gender = "male" if male_prob > female_prob else "female"
if gender == "male":
return (gender, male_prob)
return (gender, female_prob)
And here is the extract_feature function where I load the file and process it:
def extract_feature(file_name, **kwargs):
mfcc = kwargs.get("mfcc")
chroma = kwargs.get("chroma")
mel = kwargs.get("mel")
contrast = kwargs.get("contrast")
tonnetz = kwargs.get("tonnetz")
X, sample_rate = librosa.core.load(file_name)
if chroma or contrast:
stft = np.abs(librosa.stft(X))
result = np.array([])
if mfcc:
mfccs = np.mean(librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40).T, axis=0)
result = np.hstack((result, mfccs))
if chroma:
chroma = np.mean(librosa.feature.chroma_stft(S=stft, sr=sample_rate).T,axis=0)
result = np.hstack((result, chroma))
if mel:
mel = np.mean(librosa.feature.melspectrogram(X, sr=sample_rate).T,axis=0)
result = np.hstack((result, mel))
if contrast:
contrast = np.mean(librosa.feature.spectral_contrast(S=stft, sr=sample_rate).T,axis=0)
result = np.hstack((result, contrast))
if tonnetz:
tonnetz = np.mean(librosa.feature.tonnetz(y=librosa.effects.harmonic(X), sr=sample_rate).T,axis=0)
result = np.hstack((result, tonnetz))
return result
What am I doing wrong? Is there a way to create a valid WAV file having the same content as the blob that I record on the frontend? Or is there a way to directly use the blob that I receive from the frontend?
After some digging, I discovered the ffmpeg tool on Linux and I used it in python to convert the file from WebM format to WAV. Here is the solution:
def post(self, request):
webm_file = str(datetime.datetime.now()) + ".webm"
wav_file = str(datetime.datetime.now()) + ".wav"
f = request.FILES['file']
with open(webm_file, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
destination.close()
# convert file from WebM to WAV format
subprocess.run(["ffmpeg", "-i", webm_file, "-vn", wav_file])
(prediction, probability) = predict(wav_file)
context["prediction"] = prediction
context["probability"] = probability*100
os.remove(webm_file)
os.remove(wav_file)
return render(request, self.template_name, context=context)

Uncaught ReferenceError: characters is not defined

I am creating a simple rest api in javascript, I want upon initialization, the widget must display a list of all characters.
here is folder structure :
├───book
└───book.js
├───store
│ └───store.js
here is my store.js
window.Store = {
create: function() {
var self = {};
var props = {
name: 'string',
species: 'string',
picture: 'string',
description: 'string'
};
var listProps = ['name', 'species'];
var detailProps = ['name', 'species', 'picture', 'description'];
var characters = [
{
id: makeID(),
name: 'Ndiefi',
species: 'Wookie',
picture: 'store/img/ndiefi.png',
description: 'A legendary Wookiee warrior and Han Solo’s co-pilot aboard the Millennium Falcon, Chewbacca was part of a core group of Rebels who restored freedom to the galaxy. Known for his short temper and accuracy with a bowcaster, Chewie also has a big heart -- and is unwavering in his loyalty to his friends. He has stuck with Han through years of turmoil that have changed both the galaxy and their lives.',
_delay: 500
},
];
}
}
here is index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Character Book</title>
<!-- 3rd party vendor libraries -->
<link rel="stylesheet" href="vendor/font-awesome-4.6.3/css/font-awesome.min.css">
<script src="vendor/jquery-3.1.0.min.js"></script>
<script src="vendor/underscore-1.8.3.min.js"></script>
<!-- 1st party internal libraries -->
<script src="store/store.js"></script>
<script src="tests/start-test.js"></script>
<script src="tests/test-book.js"></script>
<!-- The source of the 'Book' widget -->
<link href="book/book.css" rel="stylesheet">
<script src="book/book.js"></script>
<script>
$(function() {
var frame = $('#test-frame');
var run = $('#test-run');
var results = $('#test-results');
var store = Store.create();
run.click(function() {
run.prop('disabled', true).text('Running Tests');
results.removeClass('test-pass test-fail').text('');
testBook(frame).then(
function success() {
run.prop('disabled', false).text('Run Tests');
results.addClass('test-pass').text('All tests passed');
},
function failure(err) {
run.prop('disabled', false).text('Run Tests');
results.addClass('test-fail').text('Test failed, see console');
}
);
});
Book.init(frame, store);
});
</script>
</head>
<body>
<button id="test-run">Run Tests</button>
<span id="test-results"></span>
<div id="test-frame">
</div>
</body>
</html>
here is what I have tried :
books.js
var data = JSON.parse(characters);
data.forEach(characters => {
console.log(characters.name)
});
so when I run the app in my browser I see the following error :
Uncaught ReferenceError: characters is not defined
what is wrong with my code ? any suggestion or help will be helpfull thanks

JSON object is not being rendered in charts js: Django

I have implemented chart JS 2.5 into my django application version 1.11 but I am able to see only the canvas but not any bar chart, besides,the web browser console does not display any error, so this is becoming quite difficult for me to trace the mistake.
statistics.html and views.py are my main files where I am currently trying to debug this problem. The urls.py and header.html files were not touched recently and I put them at the end.
statistics.html file:
Graph implementation and retrieval of the JSON object
{% extends "personal_website/header.html"%}
<script>
{% block jquery %}
var endpoint = '/statistics/data'
var defaultData = []
var labels = []
$.ajax({
method: "GET",
url: endpoint,
dataType: 'json',
success: function(data){
labels = data.labels
defaultData = data.default
var ctx = document.getElementById("myChart")
var myChart = new Chart(ctx, {
type:'bar',
data: {
labels: labels,
datasets : [{
label: '# of votes',
data: defaultData,
}]
}
})
},
error: function(error_data){
console.log("error on data")
console.log(error_data)
}
})
{% endblock %}
</script>
{% block content %}
<div class ='row'>
<div class="col-sm-12" url-endpoint='{% url "get_data" %}'>
<h1>Statistics for week 21</h1>
<canvas id="myChart" width="400" height="400"></canvas>
</div>
</div>
{% endblock content %}
Views.py
get_data() was used to test if I could receive the JSON object through the web browser console.
from django.shortcuts import render
from django.views.generic import View
from django.http import JsonResponse
from django.template.loader import render_to_string
from rest_framework.views import APIView
from rest_framework.response import Response
def index(request):
return render(request, 'personal_website/home.html')
def statistics(request):
return render(request, 'personal_website/statistics.html',{})
def get_data(request, *args, **kwargs):
response_data = {}
response_data["customers"] = 100
response_data["sales"] = 40 *12
return JsonResponse(response_data)
class ChartData(APIView):
def get(self,request,format=None):
labels = ["Red","Blue","Yellow","Green","Purple","Orange"]
default_items = [22,35,12,8,10,9]
data = {
"labels": labels,
"default": default_items,
}
return Response(data)
urls.py
from django.conf.urls import url, include
from . import views
from .views import ChartData, get_data
urlpatterns = [
url(r'^$', views.index, name='index'), # home
url(r'^statistics/$', views.statistics, name='statistics'),
url(r'^statistics/data$', get_data, name='get_data'),
url(r'^statistics/chart-data$', ChartData.as_view()), # API View working) ]
header.html
<head>
<title>Statistics</title>
<meta charset="utf-8" />
{% load staticfiles %}
<meta name="viewport" content="width=device=width, initial-scale=1.0">
</head>
<body class="body" style="background-color:#f6f6f6">
<div class="container-fluid" style="min-height:95%; ">
<div class="row">
<div class="col-sm-10">
<h3>Statistics</h3>
</div>
</div><hr>
<div class="well bs-sidebar" id="sidebar">
<ul class="nav nav-pills nav-stacked">
<li><a href='/'>Home</a></li>
<li><a href='/statistics/'>Statistics</a></li>
</ul>
</div>
</div>
<footer>
<!-- no content for the moment-->
</footer>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js">
</script>
</html>
Lastly, the only part that I see that changes is is the label: '# of votes' from the dataset.
What is missing in the code, so I can see the displayed bar charts?
Any help, suggestion, improvement, question is welcome.

EJS View Not Rendering

I am trying to load ejs templates in my express app. I set the 'view engine' to ejs and, passed an ejs template to the response.render. However,when I am navigating to localhost:8000, I am only seeing the include statements in literal form.
The template file:
index.ejs
{% include('commonheader') %}
<div id='mainbody' class='container-fluid'>
<nav>
{%- include('mainheader', {
navbar: navbar_options
}) %}
</nav>
</div>
{%- include('commonfooter', {
footer: sitemap
}) %}
commonheader.ejs
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title><%= title %></title>
<!-- bootstrap -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<!-- bootstrap js -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<!-- Jquery -->
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<!-- Custom stylesheets and js -->
<%- if(stylesheets){
if(typeof stylesheets == []){
Array.prototype.forEach(function(sheet){
%}<link rel='stylesheet' href= {%= sheet %}>{%
}, stylesheets);
}
else{
%}<link rel='stylesheet' href= {%= Array.prototype.shift.call(stylesheets) %}>{%;
}
}; %}
</head>
<body>
commonfooter.ejs
<footer>
<% if(footer){
for(let k in footer){
if(typeof footer[k] []){
Array.prototype.forEach.call(function(link){
%}<a href= {%= link['href'] %}>
<li>{%= link['name'] %}</li>
</a>{%
});
}
else{
%}<a href= {%= link['href'] %}>
<ul>{%= link['name'] %}</ul>{%
}
}
%}
</footer>
</body>
</html>
routes.js
const express = require('express');
const path = require('path');
const appinst = express();
const _template_dir = '/static';
const _root_addr = '127.0.0.1:8000';
// bind render engine to ejs
appinst.set('views', path.join(__dirname,'views'));
appinst.set('view engine', 'ejs');
appinst.get('/', function(request, response){
response.render('index', {
css_stylesheets: [
'css/index.css',
],
navbar_options: [
{
'href': _root_addr + '/',
'name': 'Home'
},
{
'href': _root_addr + '/create',
'name': 'Create'
},
{
'href': _root_addr + '/howto',
'name': 'How To'
}
],
sitemap: [
{
'href': _root_addr + '/',
'name': 'Home'
},
{
'href': _root_addr + '/aboutus',
'name': 'About Us'
},
{
'href': _root_addr + '/create',
'name': 'Create'
},
{
'href': _root_addr + '/howto',
'name': 'How To'
},
{
'href': _root_addr + '/contactus',
'name': 'Contact Us'
}
]
});
});
Browser Output:
{% include('commonheader') %}
{%- include('mainheader', { navbar: navbar_options }) %}
{%- include('commonfooter', { footer: sitemap }) %}
i think you mistyped the inclusion, should look like this:
<%- include('mainheader', { navbar: navbar_options }); %>
but from your code you're missing the opening and closing tag <%- %>
you're only using the %- and %
{%- include('mainheader', { navbar: navbar_options }) %}

How to show custom server errors in UI using Plupload and Symfony3

INTRODUCTION
In order to upload multiple files to the server I am using:
Symfony v3.2.6
OneUpUploaderBundle
OneUpFlysystemBundle
Plupload file uploading library
NOTE
Please note that: this configuration works without a hitch for single and multiple file uploads. It just does not show custom server errors in the clients browser.
TARGET
I would like to show file exists error in UI
PROBLEM
I am using validator to restrict some uploadable files.
At the moment files that validator restricts are not uploaded (ValidationException is beeing trown).
I do not know how to make Plupload to show file already exist errors.
CODE
My template with relevant javascript code
{% extends 'base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link type="text/css" rel="stylesheet" href="{{ asset('js/plupload/jquery-ui-1.12.1/jquery-ui.css') }}" />
<link type="text/css" rel="stylesheet" href="{{ asset('js/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css') }}" media="screen" />
{% endblock %}
{% block content %}
<div id="box-upload">
<div id="uploader">
<p>Your browser doesn't have HTML5 support.</p>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script type="text/javascript" src="{{ asset('js/browserplus/browserplus.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/plupload/plupload.full.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/jquery-2.2.4.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/plupload/jquery-ui-1.12.1/jquery-ui.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/plupload/jquery.ui.plupload/jquery.ui.plupload.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/plupload/i18n/lv.js') }}"></script>
<script type="text/javascript">
'use strict';
$(function()
{
var uploader;
uploader = $("#uploader");
uploader.plupload(
{
// General settings
runtimes: 'html5',
url: "{{ oneup_uploader_endpoint('gallery') }}",
multi_selection: true,
// Maximum file size
max_file_size: '5mb',
chunk_size: '5mb',
// Specify what files to browse for
filters: [
{title: "Image files", extensions: "jpg,jpeg,png,gif"},
{title: "Zip files", extensions: "zip,7z"},
{title: "Pdf files", extensions: "pdf"},
{title: "Binary files", extensions: "bin"},
{title: "Text files", extensions: "txt"},
{title: "Media files", extensions: "avi"}
],
// Rename files by clicking on their titles
rename: true,
// Sort files
sortable: true,
// Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
dragdrop: true,
// Views to activate
views: {
list: true,
thumbs: false, // Show thumbs
active: 'list'
}
});
var $uploader = uploader.plupload('getUploader');
// Add Clear Button
var $button = $("<button>"+ plupload.translate("Clear list") + "</button>").button({icons: {primary: "ui-icon-trash"}}).button("disable").appendTo('.plupload_buttons');
// Clear Button Action
$button.click(function()
{
removeErrorMessages();
$uploader.splice();
$(".plupload_filelist_content").html('');
$button.button("disable");
return true;
});
// Clear Button Toggle Enabled
$uploader.bind('QueueChanged', function ()
{
if ($uploader.files.length > 0)
{
$button.button("enable");
}
else
{
$button.button("disable");
}
});
// Clear Button Toggle Hidden
$uploader.bind('StateChanged', function ()
{
if ($uploader.state == plupload.STARTED)
{
$button.hide();
}
else
{
$button.show();
}
});
// Clear Button Toggle Hidden
$uploader.bind('Browse', function ()
{
removeErrorMessages();
$uploader.splice();
});
$uploader.bind('Error', function(uploader, error)
{
console.error(error.message);
console.log(error.message);
});
function removeErrorMessages()
{
$(".ui-state-error").remove();
}
});
</script>
{% endblock %}
My validator
<?php
namespace AppBundle\EventListener;
use Oneup\UploaderBundle\Event\ValidationEvent;
use Oneup\UploaderBundle\Uploader\Exception\ValidationException;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class AllowedMimeTypeValidationListener
{
/**
* #var Container
*/
private $container;
private $file_extension_array = [];
private $file_type_array = [];
private $banned_files = [];
public function __construct(Container $container)
{
$this->container = $container;
}
public function onValidate(ValidationEvent $event)
{
$ultra_helpers = $this->container->get('app.ultra_helpers');
$ultra_text = $this->container->get('app.ultra_text');
array_push($this->file_extension_array, '.gif');
array_push($this->file_extension_array, '.jpg');
array_push($this->file_extension_array, '.jpeg');
array_push($this->file_extension_array, '.png');
array_push($this->file_extension_array, '.zip');
array_push($this->file_extension_array, '.7z');
array_push($this->file_extension_array, '.pdf');
array_push($this->file_extension_array, '.bin');
array_push($this->file_extension_array, '.txt');
array_push($this->file_type_array, 'image/gif');
array_push($this->file_type_array, 'image/jpg');
array_push($this->file_type_array, 'image/jpeg');
array_push($this->file_type_array, 'image/png');
array_push($this->file_type_array, 'application/zip');
array_push($this->file_type_array, 'application/x-7z-compressed');
array_push($this->file_type_array, 'application/pdf');
array_push($this->file_type_array, 'application/octet-stream');
array_push($this->file_type_array, 'text/plain');
array_push($this->banned_files, 'do_not_allow_me_1.txt');
array_push($this->banned_files, 'do_not_allow_me_3.txt');
array_push($this->banned_files, 'do_not_allow_me_2.txt');
$file = $event->getFile();
$file_extension = '.'. $file->getExtension();
$file_mime_type = $file->getMimeType();
$file_info = $ultra_helpers->filterFileInfoFromFilename($file->getClientOriginalName());
$transliterated_file_name = $ultra_text->transliterateText($file_info['name']);
$full_file_name = $transliterated_file_name .'.'. $file_info['extension'];
if (in_array($full_file_name, $this->banned_files))
{
throw new ValidationException('error.file_exists');
}
// Is file mime type the same as extension mime type
$mime_type_position = array_search($file_extension, $this->file_extension_array);
if ($mime_type_position !== false)
{
$mime_type_by_extension = $this->file_type_array[$mime_type_position];
if ($mime_type_by_extension !== $file_mime_type)
{
throw new ValidationException('error.mime_type_mismatch');
}
}
// Is file type not in activated file type array
if (!in_array($file_mime_type, $this->file_type_array))
{
throw new ValidationException('error.forbidden_mime_type');
}
}
}
FINALLY
What am I missing?
CONCLUSION
Please advise.
Thank You for your time and knowledge.
To show error in UI one has to listen to FileUploaded event and manually trigger an error (like in code example below).
$uploader.bind('FileUploaded', function(up, file, info)
{
var response;
response = jQuery.parseJSON(info.response);
// trigger error manually
up.trigger("error", {message: "Test error message", code: 12345, details: "Testing errors"});
// add some CSS class to the corresponding file in UI
$("#"+ file.id).addClass("highlight-file");
});

Categories

Resources