Skip to content
Snippets Groups Projects
Commit 791c1de7 authored by Philip ABBET's avatar Philip ABBET
Browse files

Merge branch 'plotterparams_merge' into 'master'

Plotterparams merge

See merge request !222
parents afacf3c4 821af412
No related branches found
No related tags found
1 merge request!222Plotterparams merge
Pipeline #
Showing
with 1639 additions and 45 deletions
...@@ -43,6 +43,7 @@ from .fields import JSONSerializerField, StringListField ...@@ -43,6 +43,7 @@ from .fields import JSONSerializerField, StringListField
import simplejson as json import simplejson as json
import difflib import difflib
import ast
#---------------------------------------------------------- #----------------------------------------------------------
...@@ -274,6 +275,35 @@ class ContributionSerializer(VersionableSerializer): ...@@ -274,6 +275,35 @@ class ContributionSerializer(VersionableSerializer):
#---------------------------------------------------------- #----------------------------------------------------------
class MapDot(dict):
def __init__(self, *args, **kwargs):
super(MapDot, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.iteritems():
self[k] = v
if kwargs:
for k, v in kwargs.iteritems():
self[k] = v
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(MapDot, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(MapDot, self).__delitem__(key)
del self.__dict__[key]
class ContributionCreationSerializer(serializers.ModelSerializer): class ContributionCreationSerializer(serializers.ModelSerializer):
declaration = JSONSerializerField(required=False) declaration = JSONSerializerField(required=False)
...@@ -298,18 +328,33 @@ class ContributionCreationSerializer(serializers.ModelSerializer): ...@@ -298,18 +328,33 @@ class ContributionCreationSerializer(serializers.ModelSerializer):
data['name'] = name data['name'] = name
if data.has_key('previous_version'): if data.has_key('previous_version'):
previous_version_id = self.Meta.beat_core_class.Storage(settings.PREFIX, if self.Meta.beat_core_class is not None:
data['previous_version']) previous_version_id = self.Meta.beat_core_class.Storage(settings.PREFIX,
if previous_version_id.username is None: data['previous_version'])
previous_version_id.username = user.username if previous_version_id.username is None:
previous_version_id.username = user.username
else:
previous_version_id = MapDot()
previous_version_id["username"] = user.username
previous_version_id["name"] = name
previous_version_id["version"] = data['previous_version']
data['data'] = json.dumps(ast.literal_eval(json.loads(json.dumps(data['data']))))
else: else:
previous_version_id = None previous_version_id = None
if data.has_key('fork_of'): if data.has_key('fork_of'):
fork_of_id = self.Meta.beat_core_class.Storage(settings.PREFIX, if self.Meta.beat_core_class is not None:
data['fork_of']) fork_of_id = self.Meta.beat_core_class.Storage(settings.PREFIX,
if fork_of_id.username is None: data['fork_of'])
fork_of_id.username = user.username if fork_of_id.username is None:
fork_of_id.username = user.username
else:
fork_of_id = MapDot()
fork_elem = json.loads(json.dumps(ast.literal_eval(json.loads(json.dumps(data['fork_of'])))))
fork_of_id["username"] = fork_elem['username']
fork_of_id["name"] = fork_elem['name']
fork_of_id["version"] = fork_elem['version']
data['data'] = json.dumps(ast.literal_eval(json.loads(json.dumps(data['data']))))
else: else:
fork_of_id = None fork_of_id = None
......
...@@ -71,6 +71,19 @@ beat.experiments.utils.displayPlot = function(prefix, container, value, availabl ...@@ -71,6 +71,19 @@ beat.experiments.utils.displayPlot = function(prefix, container, value, availabl
{ {
var data = JSON.parse(JSON.stringify(value)); var data = JSON.parse(JSON.stringify(value));
//sample data plot or real plot required?
var default_post_prefix = '/plotters/plot/';
var sampledata_post_prefix = '/plotters/plot_sample/';
var sampledatawithparams_post_prefix = '/plotters/plot_sample_with_params/';
var post_prefix = default_post_prefix;
if('sample_data' in data)
{
post_prefix = sampledata_post_prefix;
if('dynamic_params' in data)
post_prefix = sampledatawithparams_post_prefix;
}
data.content_type = 'image/png'; data.content_type = 'image/png';
data.base64 = true; data.base64 = true;
...@@ -83,7 +96,7 @@ beat.experiments.utils.displayPlot = function(prefix, container, value, availabl ...@@ -83,7 +96,7 @@ beat.experiments.utils.displayPlot = function(prefix, container, value, availabl
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: prefix + '/plotters/plot/', url: prefix + post_prefix,
data: data, data: data,
success: function(data) { success: function(data) {
......
...@@ -90,6 +90,11 @@ class PlotterModelForm(forms.ModelForm): ...@@ -90,6 +90,11 @@ class PlotterModelForm(forms.ModelForm):
required=False, required=False,
) )
sample_data = CodeMirrorJSONCharField(
readonly=True,
required=False,
)
class Meta: class Meta:
model = Plotter model = Plotter
exclude = [] exclude = []
...@@ -153,7 +158,8 @@ class PlotterAdmin(admin.ModelAdmin): ...@@ -153,7 +158,8 @@ class PlotterAdmin(admin.ModelAdmin):
list_display_links = ('id', 'name') list_display_links = ('id', 'name')
list_filter = ('author',) list_filter = ('author',)
readonly_fields = ('hash', 'short_description', 'dataformat', 'referenced_libraries') readonly_fields = ('hash', 'short_description', 'dataformat',
'referenced_libraries')
actions = [ actions = [
rehash_plotter, rehash_plotter,
...@@ -194,7 +200,8 @@ class PlotterAdmin(admin.ModelAdmin): ...@@ -194,7 +200,8 @@ class PlotterAdmin(admin.ModelAdmin):
('Cached Information (read-only)', ('Cached Information (read-only)',
dict( dict(
classes=('collapse',), classes=('collapse',),
fields=('dataformat', 'parameters', 'referenced_libraries'), fields=('dataformat', 'parameters', 'referenced_libraries',
'sample_data'),
), ),
), ),
('Definition', ('Definition',
...@@ -243,11 +250,17 @@ class PlotterParameterAdmin(admin.ModelAdmin): ...@@ -243,11 +250,17 @@ class PlotterParameterAdmin(admin.ModelAdmin):
'creation_date', 'creation_date',
'sharing', 'sharing',
'short_description', 'short_description',
'previous_version',
'fork_of',
) )
search_fields = ['author__username', search_fields = ['author__username',
'name', 'name',
'short_description', 'short_description',
'plotter__name', 'plotter__name',
'previous_version__author__username',
'previous_version__name',
'fork_of__author__username',
'fork_of__name',
] ]
list_display_links = ('id', 'name') list_display_links = ('id', 'name')
list_filter = ('sharing', ) list_filter = ('sharing', )
......
...@@ -51,6 +51,8 @@ from django.shortcuts import get_object_or_404 ...@@ -51,6 +51,8 @@ from django.shortcuts import get_object_or_404
from django.utils import six from django.utils import six
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
import json
class ListPlotterView(ListContributionView): class ListPlotterView(ListContributionView):
""" """
List all available plotters List all available plotters
...@@ -89,7 +91,21 @@ class ListPlotterParameterView(ListContributionView): ...@@ -89,7 +91,21 @@ class ListPlotterParameterView(ListContributionView):
dataformat__name = name, dataformat__name = name,
dataformat__version = version) dataformat__version = version)
else: else:
return self.model.objects.all() #return self.model.objects.all()
#from author and public and get latest version only
objects = self.model.objects.from_author_and_public(self.request.user, self.request.user.username).order_by('-version')
filtered_list = []
filtered_list_id = []
for the_item in objects:
check = False
for filtered_item in filtered_list:
if the_item.author == filtered_item.author and the_item.name == filtered_item.name:
check = True
if check == False:
filtered_list.append(the_item)
filtered_list_id.append(the_item.id)
objects = self.model.objects.from_author_and_public(self.request.user, self.request.user.username).order_by('-version').filter(id__in=filtered_list_id)
return objects
class ListDefaultPlotterView(generics.ListAPIView): class ListDefaultPlotterView(generics.ListAPIView):
""" """
...@@ -123,12 +139,12 @@ class CheckPlotterNameView(CheckContributionNameView): ...@@ -123,12 +139,12 @@ class CheckPlotterNameView(CheckContributionNameView):
#---------------------------------------------------------- #----------------------------------------------------------
class SharePlotterView(ShareCodeView): class SharePlotterParameterView(ShareCodeView):
""" """
This view allows to share a plotter with This view allows to share a plotterparameter with
other users and/or teams other users and/or teams
""" """
model = Plotter model = PlotterParameter
#---------------------------------------------------------- #----------------------------------------------------------
...@@ -251,7 +267,6 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi ...@@ -251,7 +267,6 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi
model = PlotterParameter model = PlotterParameter
serializer_class = FullPlotterParameterSerializer serializer_class = FullPlotterParameterSerializer
def put(self, request, author_name, object_name, version=None): def put(self, request, author_name, object_name, version=None):
if version is None: if version is None:
return BadRequestResponse('A version number must be provided') return BadRequestResponse('A version number must be provided')
...@@ -301,6 +316,9 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi ...@@ -301,6 +316,9 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi
if (short_description is not None) and (len(short_description) > self.model._meta.get_field('short_description').max_length): if (short_description is not None) and (len(short_description) > self.model._meta.get_field('short_description').max_length):
raise serializers.ValidationError({'short_description': 'Short description too long'}) raise serializers.ValidationError({'short_description': 'Short description too long'})
customdata = None
if data.has_key('customdata'):
customdata = json.dumps(data['customdata'])
# Process the query string # Process the query string
if request.GET.has_key('fields'): if request.GET.has_key('fields'):
...@@ -337,6 +355,10 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi ...@@ -337,6 +355,10 @@ class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributi
if plotter is not None: if plotter is not None:
dbplotterparameter.plotter = plotter dbplotterparameter.plotter = plotter
# Modification of the parameters
if customdata is not None:
dbplotterparameter.data = customdata
# Save the plotterparameter model # Save the plotterparameter model
try: try:
dbplotterparameter.save() dbplotterparameter.save()
......
...@@ -32,31 +32,23 @@ from . import api ...@@ -32,31 +32,23 @@ from . import api
urlpatterns = [ urlpatterns = [
url(r'^$', api.ListPlotterView.as_view(), name='all'), url(r'^$', api.ListPlotterView.as_view(), name='all'),
url(r'^format/(?P<author_name>\w+)/(?P<dataformat_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.ListFormatPlotterView.as_view(), name='object'), url(r'^format/(?P<author_name>\w+)/(?P<dataformat_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.ListFormatPlotterView.as_view(), name='object'),
url(r'^plotterparameter/$', api.ListPlotterParameterView.as_view(), name='all_plotterparameter'),
url(r'^plotterparameters/(?P<author_name>\w+)/(?P<object_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/share/$',
api.SharePlotterParameterView.as_view(),
name='share',
),
url(r'^plotterparameters/(?P<author_name>\w+)/(?P<object_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.RetrieveUpdateDestroyPlotterParametersView.as_view(), name='view'), url(r'^plotterparameters/(?P<author_name>\w+)/(?P<object_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.RetrieveUpdateDestroyPlotterParametersView.as_view(), name='view'),
url(r'^plotterparameters/(?P<author_name>\w+)/$', api.ListPlotterParametersView.as_view(), name='view'), url(r'^plotterparameters/(?P<author_name>\w+)/$', api.ListPlotterParametersView.as_view(), name='view'),
url(r'^plotterparameters/$', api.ListPlotterParameterView.as_view(), name='all_plotterparameter'),
url(r'^plotterparameter/(?P<author_name>\w+)/(?P<dataformat_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.ListPlotterParameterView.as_view(), name='plotterparameter'), url(r'^plotterparameter/(?P<author_name>\w+)/(?P<dataformat_name>[a-zA-Z0-9_\-]+)/(?P<version>\d+)/$', api.ListPlotterParameterView.as_view(), name='plotterparameter'),
url(r'^defaultplotters/$', api.ListDefaultPlotterView.as_view(), name='all_defaultplotters'), url(r'^defaultplotters/$', api.ListDefaultPlotterView.as_view(), name='all_defaultplotters'),
#url(r'^$',
# api.ListPlottersView.as_view(),
# name='all_plotters',
# ),
url(r'^check_name/$', url(r'^check_name/$',
api.CheckPlotterNameView.as_view(), api.CheckPlotterNameView.as_view(),
name='check_name', name='check_name',
), ),
#url(r'^diff/(?P<author1>\w+)/(?P<name1>[-\w]+)/(?P<version1>\d+)/(?P<author2>\w+)/(?P<name2>[-\w]+)/(?P<version2>\d+)/$',
# api.DiffPlotterView.as_view(),
# name='diff',
# ),
url(r'^(?P<author_name>\w+)/(?P<object_name>[-\w]+)/(?P<version>\d+)/share/$',
api.SharePlotterView.as_view(),
name='share',
),
url(r'^(?P<author_name>\w+)/$', url(r'^(?P<author_name>\w+)/$',
api.ListCreatePlottersView.as_view(), api.ListCreatePlottersView.as_view(),
...@@ -67,10 +59,4 @@ urlpatterns = [ ...@@ -67,10 +59,4 @@ urlpatterns = [
api.RetrieveUpdateDestroyPlottersView.as_view(), api.RetrieveUpdateDestroyPlottersView.as_view(),
name='object', name='object',
), ),
#url(r'^(?P<author_name>\w+)/(?P<object_name>[-\w]+)/$',
# api.RetrieveUpdateDestroyPlottersView.as_view(),
# name='object',
# ),
] ]
...@@ -36,3 +36,4 @@ class PlottersConfig(CommonAppConfig): ...@@ -36,3 +36,4 @@ class PlottersConfig(CommonAppConfig):
super(PlottersConfig, self).ready() super(PlottersConfig, self).ready()
from actstream import registry from actstream import registry
registry.register(self.get_model('Plotter')) registry.register(self.get_model('Plotter'))
registry.register(self.get_model('PlotterParameter'))
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import json
plot_bar_data = { "data": [ { "y": [ 4.0, 7.0, 25.0, 24.0, 30.0, 82.0, 83.0, 100.0, 116.0, 119.0, 173.0, 193.0, 179.0, 195.0, 142.0, 169.0, 131.0, 70.0, 42.0, 16.0 ], "x": [ -5673.502545751196, -5417.040747386832, -5160.578949022467, -4904.117150658103, -4647.655352293739, -4391.193553929375, -4134.731755565012, -3878.269957200647, -3621.808158836283, -3365.346360471919, -3108.8845621075548, -2852.4227637431904, -2595.9609653788266, -2339.4991670144627, -2083.0373686500984, -1826.575570285734, -1570.1137719213702, -1313.6519735570064, -1057.1901751926425, -800.7283768282778 ], "label": "negative scores" }, { "y": [ 1.0, 3.0, 2.0, 0.0, 0.0, 1.0, 1.0, 3.0, 3.0, 2.0, 2.0, 7.0, 13.0, 7.0, 11.0, 13.0, 11.0, 11.0, 6.0, 3.0 ], "x": [ -1675.9012965728323, -1597.174480302131, -1518.44766403143, -1439.7208477607287, -1360.9940314900277, -1282.2672152193263, -1203.5403989486254, -1124.8135826779242, -1046.086766407223, -967.3599501365218, -888.6331338658206, -809.9063175951195, -731.1795013244183, -652.4526850537171, -573.725868783016, -494.99905251231485, -416.27223624161365, -337.54541997091246, -258.81860370021127, -180.09178742951008 ], "label": "positive scores" } ] }
plot_isoroc_data = { "data": [ { "number_of_negatives": 1900, "false_positives": [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.03, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.07, 0.08, 0.11, 0.12, 0.14, 0.16, 0.18, 0.21, 0.27, 0.36, 0.41, 0.46, 0.56, 0.67, 0.74, 0.82, 0.91, 0.94, 0.99, 1.0 ], "number_of_positives": 100, "false_negatives": [ 1.0, 0.9994736842105263, 0.9994736842105263, 0.9989473684210526, 0.998421052631579, 0.9973684210526316, 0.9968421052631579, 0.9957894736842106, 0.9952631578947368, 0.9942105263157894, 0.9921052631578947, 0.99, 0.988421052631579, 0.9831578947368421, 0.9805263157894737, 0.978421052631579, 0.9747368421052631, 0.9726315789473684, 0.97, 0.9631578947368421, 0.9594736842105264, 0.958421052631579, 0.9552631578947368, 0.9510526315789474, 0.9431578947368421, 0.9342105263157895, 0.9210526315789473, 0.911578947368421, 0.9042105263157895, 0.8968421052631579, 0.8878947368421053, 0.8773684210526316, 0.8631578947368421, 0.8515789473684211, 0.8410526315789474, 0.8310526315789474, 0.8194736842105264, 0.8042105263157895, 0.7936842105263158, 0.7789473684210526, 0.7626315789473684, 0.7521052631578947, 0.738421052631579, 0.7221052631578947, 0.7094736842105264, 0.6952631578947368, 0.6805263157894736, 0.6631578947368421, 0.6452631578947369, 0.6242105263157894, 0.6, 0.5821052631578948, 0.5573684210526316, 0.5336842105263158, 0.5131578947368421, 0.49105263157894735, 0.4668421052631579, 0.4457894736842105, 0.42526315789473684, 0.4047368421052632, 0.38473684210526315, 0.35947368421052633, 0.3352631578947368, 0.31526315789473686, 0.2968421052631579, 0.27789473684210525, 0.2615789473684211, 0.24894736842105264, 0.23105263157894737, 0.20894736842105263, 0.18894736842105264, 0.17210526315789473, 0.1531578947368421, 0.13473684210526315, 0.12052631578947369, 0.10473684210526316, 0.08842105263157894, 0.07263157894736842, 0.061052631578947365, 0.05263157894736842, 0.045789473684210526, 0.038421052631578946, 0.030526315789473683, 0.027894736842105264, 0.017894736842105262, 0.013157894736842105, 0.009473684210526316, 0.007368421052631579, 0.005263157894736842, 0.003157894736842105, 0.002105263157894737, 0.0005263157894736842, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], "label": "roc" } ] }
plot_scatter_data = { "data": [ { "y": [ 1.0, 0.9994736842105263, 0.9989473684210526, 0.9989473684210526, 0.9989473684210526, 0.998421052631579, 0.9973684210526316, 0.9963157894736843, 0.9942105263157894, 0.9910526315789474, 0.9894736842105263, 0.988421052631579, 0.9863157894736843, 0.9831578947368421, 0.9810526315789474, 0.9752631578947368, 0.9721052631578947, 0.9652631578947368, 0.9589473684210527, 0.9536842105263158, 0.9494736842105264, 0.9421052631578948, 0.9342105263157895, 0.9205263157894736, 0.91, 0.8957894736842106, 0.8789473684210526, 0.8673684210526316, 0.8510526315789474, 0.8321052631578948, 0.8089473684210526, 0.7942105263157895, 0.7789473684210526, 0.7578947368421053, 0.738421052631579, 0.7231578947368421, 0.7063157894736842, 0.6884210526315789, 0.6610526315789473, 0.64, 0.6163157894736843, 0.5936842105263158, 0.5652631578947368, 0.5405263157894736, 0.5073684210526316, 0.47947368421052633, 0.45789473684210524, 0.4263157894736842, 0.39, 0.3563157894736842, 0.32421052631578945, 0.29947368421052634, 0.2731578947368421, 0.2463157894736842, 0.22157894736842104, 0.2005263157894737, 0.17842105263157895, 0.15736842105263157, 0.13526315789473684, 0.1163157894736842, 0.10157894736842105, 0.08526315789473685, 0.0731578947368421, 0.06368421052631579, 0.05421052631578947, 0.04368421052631579, 0.03631578947368421, 0.028421052631578948, 0.022105263157894735, 0.016842105263157894, 0.012105263157894737, 0.011052631578947368, 0.009473684210526316, 0.00631578947368421, 0.003157894736842105, 0.002631578947368421, 0.002105263157894737, 0.0005263157894736842, 0.0005263157894736842, 0.0005263157894736842, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], "x": [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.02, 0.03, 0.04, 0.04, 0.04, 0.05, 0.06, 0.07, 0.07, 0.08, 0.09, 0.09, 0.1, 0.11, 0.11, 0.12, 0.12, 0.12, 0.13, 0.13, 0.15, 0.18, 0.19, 0.21, 0.24, 0.27, 0.28, 0.33, 0.34, 0.38, 0.44, 0.47, 0.52, 0.61, 0.64, 0.68, 0.7, 0.74, 0.8, 0.88, 0.91, 0.94, 0.96, 0.97, 0.98, 0.99, 0.99, 1.0 ], "label": "roc" } ] }
def add_plotter_sample_data(apps, schema_editor):
Plotter = apps.get_model("plotters", "Plotter")
for plotter in Plotter.objects.iterator():
if plotter.name == 'bar':
plotter.sample_data = json.dumps(plot_bar_data)
elif plotter.name == 'isoroc':
plotter.sample_data = json.dumps(plot_isoroc_data)
elif plotter.name == 'scatter':
plotter.sample_data = json.dumps(plot_scatter_data)
plotter.save()
def backward_dummy(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('plotters', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='plotter',
name='sample_data',
field=models.TextField(default=b'{}', blank=True),
),
migrations.RunPython(add_plotter_sample_data,
backward_dummy)
]
# -*- coding: utf-8 -*-
# Generated by Django 1.9.5 on 2017-02-07 15:49
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('plotters', '0003_auto_20161123_1218'),
('plotters', '0002_plotter_sample_data'),
]
operations = [
]
...@@ -50,6 +50,7 @@ from ..common.models import get_contribution_description_filename ...@@ -50,6 +50,7 @@ from ..common.models import get_contribution_description_filename
from ..code.models import Code from ..code.models import Code
from ..code.models import CodeManager from ..code.models import CodeManager
from ..code.models import get_contribution_source_code_filename from ..code.models import get_contribution_source_code_filename
from ..common.models import Shareable
import simplejson import simplejson
import collections import collections
...@@ -167,6 +168,7 @@ class Plotter(Code): ...@@ -167,6 +168,7 @@ class Plotter(Code):
db_column='source_code' db_column='source_code'
) )
sample_data = models.TextField(default='{}', blank=True)
# Read-only parameters that are updated at every save(), if required # Read-only parameters that are updated at every save(), if required
referenced_libraries = models.ManyToManyField(Library, blank=True, referenced_libraries = models.ManyToManyField(Library, blank=True,
related_name='used_by_plotters', related_name='used_by_plotters',
...@@ -274,6 +276,44 @@ class PlotterParameter(Contribution): ...@@ -274,6 +276,44 @@ class PlotterParameter(Contribution):
description = models.TextField(default='', blank=True, null=True, help_text=Messages['description']) description = models.TextField(default='', blank=True, null=True, help_text=Messages['description'])
plotter = models.ForeignKey(Plotter, related_name='plotting_parameters', null=True) plotter = models.ForeignKey(Plotter, related_name='plotting_parameters', null=True)
#_____ Methods __________
def modifiable(self):
"""Can be modified if nobody points at me"""
return super(PlotterParameter, self).modifiable() and (self.defaults.count() == 0)
def deletable(self):
"""Can be deleted if nobody points at me"""
return super(PlotterParameter, self).deletable() and (self.defaults.count() == 0) and (self.sharing == Shareable.PRIVATE) and (len(self.reports.all()) == 0)
#_____ Utilities __________
def get_absolute_url(self):
return reverse(
'plotters:plotterparameter-author-view',
args=(self.author.username, self.name, self.version,),
)
def get_api_update_url(self):
'''Returns the endpoint to update this object'''
return reverse(
'api_plotters:view',
args=(self.author.username, self.name, self.version,),
)
def get_api_share_url(self):
'''Returns the endpoint to share this object'''
return reverse(
'api_plotters:share',
args=(self.author.username, self.name, self.version,),
)
class DefaultPlotter(models.Model): class DefaultPlotter(models.Model):
'''Describes the default dataformat -> plotter relationships to use''' '''Describes the default dataformat -> plotter relationships to use'''
......
...@@ -33,6 +33,7 @@ from ..code.serializers import CodeSerializer, CodeCreationSerializer ...@@ -33,6 +33,7 @@ from ..code.serializers import CodeSerializer, CodeCreationSerializer
from ..libraries.serializers import LibraryReferenceSerializer from ..libraries.serializers import LibraryReferenceSerializer
from ..dataformats.serializers import ReferencedDataFormatSerializer from ..dataformats.serializers import ReferencedDataFormatSerializer
from django.utils.encoding import smart_unicode, smart_str
import beat.core.plotter import beat.core.plotter
import simplejson as json import simplejson as json
...@@ -44,7 +45,8 @@ class PlotterSerializer(ContributionSerializer): ...@@ -44,7 +45,8 @@ class PlotterSerializer(ContributionSerializer):
class Meta(ContributionSerializer.Meta): class Meta(ContributionSerializer.Meta):
model = Plotter model = Plotter
default_fields = [ default_fields = [
'name', 'dataformat', #'name', 'dataformat',
'id', 'accessibility', 'modifiable', 'deletable', 'is_owner', 'name', 'dataformat', 'fork_of', 'last_version', 'previous_version', 'short_description', 'description', 'version', 'creation_date', 'data', 'sample_data', 'declaration',
] ]
class PlotterParameterSerializer(ContributionSerializer): class PlotterParameterSerializer(ContributionSerializer):
...@@ -53,7 +55,7 @@ class PlotterParameterSerializer(ContributionSerializer): ...@@ -53,7 +55,7 @@ class PlotterParameterSerializer(ContributionSerializer):
model = PlotterParameter model = PlotterParameter
exclude = [] exclude = []
default_fields = [ default_fields = [
'name', 'name', 'plotter',
] ]
class DefaultPlotterSerializer(DynamicFieldsSerializer): class DefaultPlotterSerializer(DynamicFieldsSerializer):
...@@ -107,30 +109,62 @@ class PlotterParameterCreationFailedException(Exception): ...@@ -107,30 +109,62 @@ class PlotterParameterCreationFailedException(Exception):
pass pass
class PlotterParameterCreationSerializer(ContributionCreationSerializer): class PlotterParameterCreationSerializer(ContributionCreationSerializer):
class Meta(ContributionCreationSerializer.Meta): class Meta(ContributionCreationSerializer.Meta):
model = PlotterParameter model = PlotterParameter
fields = ['name', 'plotter', 'data', 'version', 'previous_version', 'short_description', 'description', 'fork_of']
#beat_core_class = beat.core.PlotterParameter #beat_core_class = beat.core.PlotterParameter
def create(self, validated_data): def create(self, validated_data):
plotterparameter = None plotterparameter = None
if not validated_data.has_key("name"): if not validated_data.has_key("name"):
raise serializers.ValidationError('No name provided') raise serializers.ValidationError('No name provided')
try: try:
plotterparameter = PlotterParameter.objects.get(author=self.context['request'].user, name=validated_data['name']) plotterparameter = PlotterParameter.objects.get(author=self.context['request'].user, name=validated_data['name'], version=validated_data['version'])
except: except:
pass pass
if plotterparameter is not None: if plotterparameter is not None:
raise serializers.ValidationError('A plotterparameter with this name already exists') raise serializers.ValidationError('A plotterparameter with this name already exists')
validated_data['data'] = {} if not self.data.has_key("plotter"):
raise serializers.ValidationError('No plotter provided')
plotter = None
try:
plotter = Plotter.objects.get(id=self.data['plotter'])
except:
pass
if plotter is None:
raise serializers.ValidationError('Required plotter does not exist')
if not validated_data.has_key("data"):
validated_data['data'] = {}
#Only create new version for latest version
if validated_data.has_key("previous_version"):
if validated_data['previous_version'].version < validated_data['version'] - 1:
raise serializers.ValidationError('A new version for this plotterparameter version already exist')
#add description/short_description to new version
validated_data['short_description'] = validated_data['previous_version'].short_description
validated_data['description'] = validated_data['previous_version'].description
#Create fork
if validated_data.has_key("fork_of"):
#add description/short_description to new version
validated_data['short_description'] = validated_data['fork_of'].short_description
validated_data['description'] = validated_data['fork_of'].description
plotterparameter = PlotterParameter.objects.create(**validated_data) plotterparameter = PlotterParameter.objects.create(**validated_data)
if plotterparameter is None: if plotterparameter is None:
raise PlotterParameterCreationFailedException() raise PlotterParameterCreationFailedException()
return plotterparameter return plotterparameter
#---------------------------------------------------------- #----------------------------------------------------------
...@@ -160,14 +194,20 @@ class PlotterParameterAllSerializer(ContributionSerializer): ...@@ -160,14 +194,20 @@ class PlotterParameterAllSerializer(ContributionSerializer):
#---------------------------------------------------------- #----------------------------------------------------------
class FullPlotterParameterSerializer(PlotterParameterAllSerializer): class FullPlotterParameterSerializer(PlotterParameterAllSerializer):
plotters = serializers.SerializerMethodField()
class Meta(PlotterParameterAllSerializer.Meta): class Meta(PlotterParameterAllSerializer.Meta):
#exclude = ['declaration'] #exclude = ['declaration']
exclude = [] exclude = []
#default_fields = PlotterParameterAllSerializer.Meta.default_fields + PlotterParameterAllSerializer.Meta.extra_fields #default_fields = PlotterParameterAllSerializer.Meta.default_fields + PlotterParameterAllSerializer.Meta.extra_fields
default_fields = ['id', 'accessibility', 'modifiable', 'deletable', 'is_owner', 'name', 'fork_of', 'last_version', 'previous_version', 'short_description', 'description', 'version', 'creation_date', 'data', 'plotter'] default_fields = ['id', 'accessibility', 'modifiable', 'deletable', 'is_owner', 'name', 'fork_of', 'last_version', 'previous_version', 'short_description', 'description', 'version', 'creation_date', 'data', 'plotter', 'plotters']
def get_description(self, obj):
return smart_unicode(obj.description, encoding='utf-8', strings_only=False, errors='strict')
def get_short_description(self, obj):
return smart_unicode(obj.short_description, encoding='utf-8', strings_only=False, errors='strict')
def get_data(self, obj): def get_data(self, obj):
return json.loads(obj.data) return json.loads(obj.data)
...@@ -178,6 +218,17 @@ class FullPlotterParameterSerializer(PlotterParameterAllSerializer): ...@@ -178,6 +218,17 @@ class FullPlotterParameterSerializer(PlotterParameterAllSerializer):
else: else:
return "undefined plotter" return "undefined plotter"
def get_plotters(self, obj):
all_plotters = Plotter.objects.all()
serializer = FullPlotterSerializer
results = {}
for plotter in all_plotters.iterator():
serializer = FullPlotterSerializer(plotter, fields=['id', 'accessibility', 'modifiable', 'deletable', 'is_owner', 'name', 'fork_of', 'last_version', 'previous_version', 'short_description', 'description', 'version', 'creation_date', 'data', 'sample_data', 'declaration'])
results[plotter.fullname()] = serializer.data
return results
#def get_plotter(self, obj): #def get_plotter(self, obj):
# return obj.author.username # return obj.author.username
......
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
var app = angular.module('plotterparameterApp');
app.config(function configureStartEndSymbol($interpolateProvider) {
$interpolateProvider.startSymbol('{$').endSymbol('$}');
}
);
app.config(function configHttp($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.withCredentials = true;
}
);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
var app = angular.module('plotterparameterApp', ['ui.router', 'angular.filter']);
app.config(function ($stateProvider, $urlRouterProvider){
$urlRouterProvider
.otherwise('/');
$stateProvider
.state('plotterparameter', {
url: '/',
views: {
}
})
});
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
//This controller retrieves data from the reportFactory/experimentFactory through the REST API and associates it with the $scope
//The $scope is ultimately bound to the report view
//app.controller('plotterparameterController',['$scope', 'reportFactory', 'experimentFactory', 'plotterFactory', 'dataFactory', '$q', function ($scope, reportFactory, experimentFactory, plotterFactory, dataFactory, $q)
app.controller('plotterparameterController',['$scope', 'plotterFactory', 'plotterparameterFactory', '$q', function ($scope, plotterFactory, plotterparameterFactory, $q)
{
$scope.q = $q;
$scope.user;
$scope.plotterparameter_id;
$scope.url_prefix;
$scope.plotterFactory = plotterFactory;
$scope.plotterparameterFactory = plotterparameterFactory;
$scope.plotters = {};
$scope.plotters.selected = undefined;
$scope.plotterparameterData = {};
$scope.textdata = [];
$scope.plotterparams_update = {};
$scope.plotterparams_newversion = {};
$scope.plotterparams_fork = {};
$scope.plotterparameter_forking = undefined;
$scope.init = function(user, plotterparameter, url_prefix, data_itemcontent_file, data_table_itemcontent_file)
{
$scope.user = user;
$scope.plotterparameter = plotterparameter;
$scope.plotterparameter_user = plotterparameter.split("/")[0];
$scope.plotterparameter_name = plotterparameter.split("/")[1];
$scope.plotterparameter_version = plotterparameter.split("/")[2];
$scope.url_prefix = url_prefix;
if($scope.plotterparameter == 'CREATION_MODE')
{
getPlottersData($scope.user);
}
else
{
getPlotterParameterData($scope.user, $scope.plotterparameter_user, $scope.plotterparameter_name, $scope.plotterparameter_version);
}
}
function getPlottersData(user)
{
plotterFactory.getPlottersInformation(user, $scope.url_prefix)
.success(function (plottersData)
{
$scope.plotters = plottersData;
for(var init_selected_plotter in plottersData)
{
$scope.plotters.selected = init_selected_plotter.name;
}
})
.error(function (error)
{
$scope.status = 'Unable to load report data: ' + error.message;
});
$('#tabs_progress').hide();
}
function getPlotterParameterData(user, plotterparameter_user, plotterparameter_name, plotterparameter_version)
{
plotterparameterFactory.getPlotterParameterInformation(user, plotterparameter_user, plotterparameter_name, plotterparameter_version, $scope.url_prefix)
.success(function (plotterparameterData)
{
$scope.plotters = plotterparameterData.plotters;
for(var init_selected_plotter in plotterparameterData.plotters)
{
$scope.plotters.selected = init_selected_plotter;
}
$scope.plotterparameterData = plotterparameterData;
if(plotterparameterData.plotter != "undefined plotter")
{
//Find selected plotter
$.each(plotterparameterData.plotters, function( key, value ) {
if(key == plotterparameterData.plotter)
{
$scope.plotters.selected = value;
//break
return false;
}
});
$.each($scope.plotters.selected.declaration.parameters, function( key, value ) {
//push all keys in array
$scope.textdata.push(key);
//check if already saved key/values for this plotterparameter and add
$.each($scope.plotterparameterData.data, function(keysaved, valuesaved){
if(key == keysaved)
{
$scope.plotterparams_update[keysaved] = valuesaved;
return false;
}
});
});
//$scope.textdata = $scope.plotters.selected.declaration.parameters;
addParametersToEditor();
}
})
.error(function (error)
{
$scope.status = 'Unable to load report data: ' + error.message;
});
$('#tabs_progress').hide();
}
function addParametersToEditor()
{
$scope.$broadcast("addParametersElement");
}
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
//This factory retrieves data from the REST API and associates it with the $scope
app.factory('plotterFactory', ['$http', function($http)
{
var plotterFactory = {};
plotterFactory.getPlottersInformation = function (user, url_prefix)
{
urlBase = url_prefix + '/api/v1/plotters';
return $http({
headers: {'Content-Type': 'application/json'},
url: urlBase + '/',
method: "GET",
})
};
return plotterFactory;
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
//This factory retrieves data from the REST API and associates it with the $scope
app.factory('plotterparameterFactory', ['$http', function($http)
{
var plotterparameterFactory = {};
plotterparameterFactory.getPlotterParameterInformation = function (user, plotterparameter_user, plotterparameter_name, plotterparameter_version, url_prefix)
{
urlBase = url_prefix + '/api/v1/plotters/plotterparameters';
return $http({
headers: {'Content-Type': 'application/json'},
url: urlBase + '/' + plotterparameter_user + '/' + plotterparameter_name + '/' + plotterparameter_version + '/',
method: "GET",
})
};
plotterparameterFactory.updatePlotterParameter = function (user, plotterparameter_user, plotterparameter_name, plotterparameter_version, plotterparameterData, url_prefix)
{
urlBase = url_prefix + '/api/v1/plotters/plotterparameters';
return $http({
headers: {'Content-Type': 'application/json'},
url: urlBase + '/' + user + '/' + plotterparameter_name + '/' + plotterparameter_version + '/',
method: "PUT",
data: plotterparameterData,
})
};
plotterparameterFactory.createPlotterParameter = function (user, plotterparameterData, url_prefix)
{
urlBase = url_prefix + '/api/v1/plotters/plotterparameters';
return $http({
headers: {'Content-Type': 'application/json'},
url: urlBase + '/' + user + '/',
method: "POST",
data: plotterparameterData,
})
};
return plotterparameterFactory;
}]);
.toggle label {
color: #444;
float: left;
line-height: 26px;
}
.toggle .toggle-button {
margin: 0px 10px 0px 0px;
float: left;
width: 70px;
height: 26px;
background-color: #eeeeee;
background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#fafafa));
background-image: -webkit-linear-gradient(top, #eeeeee, #fafafa);
background-image: -moz-linear-gradient(top, #eeeeee, #fafafa);
background-image: -o-linear-gradient(top, #eeeeee, #fafafa);
background-image: -ms-linear-gradient(top, #eeeeee, #fafafa);
background-image: linear-gradient(top, #eeeeee, #fafafa);
filter: progid:dximagetransform.microsoft.gradient(GradientType=0, StartColorStr='#eeeeee', EndColorStr='#fafafa');
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border: 1px solid #D1D1D1;
}
.toggle .toggle-button .toggle-tab {
width: 30px;
height: 26px;
background-color: #fafafa;
background-image: -webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#eeeeee));
background-image: -webkit-linear-gradient(top, #fafafa, #eeeeee);
background-image: -moz-linear-gradient(top, #fafafa, #eeeeee);
background-image: -o-linear-gradient(top, #fafafa, #eeeeee);
background-image: -ms-linear-gradient(top, #fafafa, #eeeeee);
background-image: linear-gradient(top, #fafafa, #eeeeee);
filter: progid:dximagetransform.microsoft.gradient(GradientType=0, StartColorStr='#fafafa', EndColorStr='#eeeeee');
border: 1px solid #CCC;
margin-left: -1px;
margin-top: -1px;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-webkit-box-shadow: 5px 0px 4px -5px #000000, 0px 0px 0px 0px #000000;
-moz-box-shadow: 5px 0px 4px -5px rgba(0, 0, 0, 0.3), 0px 0px 0px 0px #000000;
box-shadow: 5px 0px 4px -5px rgba(0, 0, 0, 0.3), 0px 0px 0px 0px #000000;
}
.toggle input[type=checkbox] {
display: none;
}
.toggle input[type=checkbox]:checked ~ label .toggle-button {
background-color: #2d71c2;
background-image: -webkit-gradient(linear, left top, left bottom, from(#2d71c2), to(#4ea1db));
background-image: -webkit-linear-gradient(top, #2d71c2, #4ea1db);
background-image: -moz-linear-gradient(top, #2d71c2, #4ea1db);
background-image: -o-linear-gradient(top, #2d71c2, #4ea1db);
background-image: -ms-linear-gradient(top, #2d71c2, #4ea1db);
background-image: linear-gradient(top, #2d71c2, #4ea1db);
filter: progid:dximagetransform.microsoft.gradient(GradientType=0, StartColorStr='#2d71c2', EndColorStr='#4ea1db');
}
.toggle input[type=checkbox]:checked ~ label .toggle-button .toggle-tab {
margin-left: 39px;
background-color: green;
-webkit-box-shadow: -5px 0px 4px -5px #000000, 0px 0px 0px 0px #000000;
-moz-box-shadow: -5px 0px 4px -5px rgba(0, 0, 0, 0.3), 0px 0px 0px 0px #000000;
box-shadow: -5px 0px 4px -5px rgba(0, 0, 0, 0.3), 0px 0px 0px 0px #000000;
}
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/**
* beat.plotterparameters.dialogs.js
* Implementation of experiment-related dialogs
*/
/**
* Setup an input box so that it does automatic experiment name completion, so
* the user knows what **not** to choose.
*
* This function requires 'bootstrap3-typeahead' to be installed
*
* Parameters:
*
* selector (str): A jQuery selector for the input box to rig
* data (Array): A JS array containing the existing names for the user
* experiments
* own (str): My own name, if one was set, so we don't mistakenly highlight
* my own (previously set) experiment, which continues to be a valid
* choice.
*/
if (beat === undefined) var beat = {};
if (beat.plotterparameters === undefined) beat.plotterparameters= {};
if (beat.plotterparameters.dialogs === undefined) beat.plotterparameters.dialogs = {};
beat.plotterparameters.dialogs.name_typeahead = function(selector, data, own) {
var element = $(selector);
var check_validity = function() {
var currval = element.val();
if (!currval.length) {
element.parent().removeClass('has-success').addClass('has-error');
element.siblings('span.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-remove');
return; //ok, we don't need to check the rest
}
if (own !== undefined && own == currval) {
element.parent().removeClass('has-error').addClass('has-success');
element.siblings('span.glyphicon').removeClass('glyphicon-remove').addClass('glyphicon-ok');
return; //ok, we don't need to check the rest
}
if ($.inArray(currval, data) >= 0) {
element.parent().removeClass('has-success').addClass('has-error');
element.siblings('span.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-remove');
}
else {
element.parent().removeClass('has-error').addClass('has-success');
element.siblings('span.glyphicon').removeClass('glyphicon-remove').addClass('glyphicon-ok');
}
}
check_validity(); //checks if the currently value set is OK
element.on('keyup', check_validity);
element.typeahead({
source: data,
items: 10, //how many to show at a time
minLength: 0, //show suggestions even if no text available
autoSelect: false, //user may want to leave it where it is
afterSelect: check_validity, //updates after the user selected an item
showHintOnFocus: true, //dropdown as soon as focus on
});
}
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/* Implementation of the new plotterparameter dialog */
// Declaration of our namespaces
if (beat === undefined) var beat = {}
if (beat.plotters === undefined) beat.plotters = {}
/**
* Uses bootstrap3 to display a modal window to create a plotterparameter. The user is
* presented with a "typeahead" input box so they can choose a name for their
* plotterparameter. The typeahead auto-completion works for the list of plotterparameters the user
* current has on their portfoglio.
*
* Parameters:
*
* url (String): A string with the URL to retrieve existing plotterparameter
* names and to create plotterparameters
* username (String): The name of the user requesting the operation
*
**/
beat.plotters.new_plotterparameter = function (url, username) {
//retrieve list of existing searches - if that succeeds, construct modal form
function create() {
return $.ajax({
type: 'GET',
url: url + '?fields=name',
}).pipe(function(data) {
var message = $(document.createElement('div'));
message.append($(document.createElement('p')).text('By clicking Save, you will create a new plotterparameter under the defined name. You can cancel the operation by clicking Cancel.'));
var form_group = $(document.createElement('div'));
form_group.addClass('form-group has-feedback');
message.append(form_group);
var input_group = $(document.createElement('div'));
input_group.addClass('input-group');
input_group.append($(document.createElement('span')).addClass('input-group-addon').text(username + ' /'));
var input = $(document.createElement('input')).addClass('form-control');
input.attr('type', 'text');
input.attr('placeholder', 'Start typing for auto-completion...');
if (name) input.val(name.split('/')[1]);
input_group.append(input);
glyph = $(document.createElement('span'));
glyph.addClass('glyphicon glyphicon-ok form-control-feedback');
glyph.attr('aria-hidden', 'true');
input_group.append(glyph);
form_group.append(input_group);
var available_names = {};
data.forEach(function(i){available_names[i.name.split('/')[1]]=i;});
var available_name_keys = Object.keys(available_names);
//visual feedback if new or overwriting...
var help = $(document.createElement('span')).addClass('help');
form_group.append(help);
var update_help = function() {
var currval = input.val();
if (!currval.length || available_name_keys.indexOf(currval) >= 0) {
help.text('plotterparameter name is invalid.');
form_group.removeClass('has-success');
form_group.addClass('has-error');
glyph.removeClass('glyphicon-ok');
glyph.addClass('glyphicon-remove');
}
else {
help.text('');
form_group.removeClass('has-error');
form_group.addClass('has-success');
glyph.removeClass('glyphicon-remove');
glyph.addClass('glyphicon-ok');
}
}
update_help(); //checks currently set value
input.on('keyup', update_help);
//using bootstrap3-typeahead
input.typeahead({
source: Object.keys(available_names),
items: 5, //how many to show at a time
minLength: 0, //show suggestions even if no text available
autoSelect: false, //user may want to leave it where it is
afterSelect: update_help, //updates after the user selected an item
showHintOnFocus: true, //dropdown as soon as focus on
});
BootstrapDialog.show({
title: '<i class="fa fa-floppy-o fa-lg"> Select a name',
message: message,
type: BootstrapDialog.TYPE_PRIMARY,
buttons: [
{
label: 'Cancel',
cssClass: 'btn-default',
action: function(the_dialog) {
the_dialog.close();
return false;
},
},
{
label: 'Create',
cssClass: 'btn-primary',
action: function(the_dialog) {
var val = input.val();
if (!val) {
BootstrapDialog.alert({
title: '<i class="fa fa-warning"></i> Error',
message: 'You must set a name to create your plotterparameter',
type: BootstrapDialog.TYPE_WARNING,
});
return false;
}
else if (available_name_keys.indexOf(val) >= 0) {
BootstrapDialog.alert({
title: '<i class="fa fa-warning"></i> Error',
message: 'You must use a non-existing plotterparameter name',
type: BootstrapDialog.TYPE_WARNING,
});
return false;
}
the_dialog.close();
if (val) {
var d = $.ajax({
type: 'POST',
url: url,
data: JSON.stringify({name: val}),
contentType: "application/json; charset=utf-8",
dataType: "json"
});
d.done(function(data, status) {
the_dialog.close();
location.reload();
return true;
});
d.fail(process_error);
} //val is set
},
},
],
});
});
}
return create().fail(process_error);
}
{% comment %}
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
<div id="{{ dialog_id }}" class="new_plotterparameter_dialog" title="Please enter a plotterparameter name..." style="display:none">
<input class="name"></input>
</div>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment