diff --git a/model_validation_api/admin.py b/model_validation_api/admin.py index 91116b7d4..af269e3b8 100644 --- a/model_validation_api/admin.py +++ b/model_validation_api/admin.py @@ -3,39 +3,105 @@ ScientificModel, ScientificModelInstance, ScientificModelImage, CollabParameters, Param_DataModalities, Param_TestType, Param_Species, - Param_BrainRegion, Param_CellType, Param_ModelType) + Param_BrainRegion, Param_CellType, Param_ModelType, Param_ScoreType,Param_organizations, + Tickets, Comments) admin.site.site_header = "HBP Validation Service administration" @admin.register(ValidationTestDefinition) class ValidationTestDefinitionAdmin(admin.ModelAdmin): - list_display = ('name', 'brain_region', 'cell_type', + list_display = ('id','name','alias', 'species', 'brain_region', 'cell_type', 'data_type', 'data_modality', 'test_type', - 'publication', 'author', 'score_type') - list_filter = ('brain_region', 'cell_type', 'test_type', 'score_type') - search_fields = ('name', 'protocol') + 'publication', 'author', 'score_type', 'age', 'data_location', 'protocol', 'creation_date') + list_filter = ('brain_region', 'cell_type', 'test_type', 'score_type', 'species', 'data_modality',) + search_fields = ('id','name','alias', 'species', 'brain_region', 'cell_type', + 'data_type', 'data_modality', 'test_type', + 'publication', 'author', 'score_type', 'age', 'data_location', 'protocol', 'creation_date') @admin.register(ValidationTestCode) class ValidationTestCodeAdmin(admin.ModelAdmin): - pass + list_display = ('id', 'repository', 'version', 'description', 'parameters', 'path', 'timestamp', 'test_definition') + # list_filter = () + search_fields = ('id', 'repository', 'version', 'description', 'parameters', 'path', 'timestamp', 'test_definition') @admin.register(ValidationTestResult) class ValidationTestResultAdmin(admin.ModelAdmin): - list_display = ('model_version', 'test_code', + list_display = ('id','model_version', 'test_code', + 'score', 'passed', 'timestamp', + 'normalized_score', 'platform', 'project') + search_fields = ('id','model_version', 'test_code', 'score', 'passed', 'timestamp', - 'normalized_score', 'platform') - search_fields = ('model_version', 'test_code') - - -admin.site.register(ScientificModel) -admin.site.register(ScientificModelInstance) -admin.site.register(ScientificModelImage) -admin.site.register(CollabParameters) -admin.site.register(Param_DataModalities) -admin.site.register(Param_TestType) -admin.site.register(Param_Species) -admin.site.register(Param_BrainRegion) -admin.site.register(Param_CellType) -admin.site.register(Param_ModelType) + 'normalized_score', 'platform', 'project') + +@admin.register(ScientificModel) +class ScientificModelAdmin(admin.ModelAdmin): + list_display = ('id','name', 'alias', 'author', 'owner', 'description', 'species', 'brain_region', 'cell_type', 'model_type', 'private', 'app', 'code_format', 'creation_date', 'organization', 'project', 'license') + search_fields = ('id','name', 'alias', 'author', 'owner', 'description', 'species', 'brain_region', 'cell_type', 'model_type', 'private', 'app', 'code_format', 'creation_date', 'organization', 'project', 'license') + list_filter = ('species', 'brain_region', 'cell_type', 'model_type', 'private', 'code_format', 'organization') + +@admin.register(ScientificModelInstance) +class ScientificModelInstanceAdmin(admin.ModelAdmin): + list_display = ('id','version', 'model', 'description', 'parameters', 'code_format', 'source', 'timestamp', 'hash') + search_fields = ('id','version', 'model', 'description', 'parameters', 'code_format', 'source', 'timestamp', 'hash') + +@admin.register(ScientificModelImage) +class ScientificModelImageAdmin(admin.ModelAdmin): + list_display = ('id', 'model', 'url', 'caption') + search_fields = ('id', 'model', 'url', 'caption') + +@admin.register(CollabParameters) +class CollabParametersAdmin(admin.ModelAdmin): + list_display = ('id', 'app_type', 'data_modalities', 'test_type', 'species', 'brain_region', 'cell_type', 'model_type', 'organization', 'collab_id') + search_fields = ('id', 'app_type', 'data_modalities', 'test_type', 'species', 'brain_region', 'cell_type', 'model_type', 'organization', 'collab_id') + +@admin.register(Param_DataModalities) +class Param_DataModalitiesAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_TestType) +class Param_TestTypeAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_Species) +class Param_SpeciesAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_BrainRegion) +class Param_BrainRegionAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_CellType) +class Param_CellTypeAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_ModelType) +class Param_ModelTypeAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_ScoreType) +class Param_ScoreTypeAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Param_organizations) +class Param_organizationsAdmin(admin.ModelAdmin): + list_display = ('id', 'authorized_value') + search_fields = ('id', 'authorized_value') + +@admin.register(Comments) +class CommentsAdmin(admin.ModelAdmin): + list_display = ('id', 'Ticket', 'author', 'text', 'creation_date') + search_fields = ('id', 'Ticket', 'author', 'text', 'creation_date') + +@admin.register(Tickets) +class TicketsAdmin(admin.ModelAdmin): + list_display = ('id', 'test', 'author', 'title', 'text', 'creation_date') + search_fields = ('id', 'test', 'author', 'title', 'text', 'creation_date') \ No newline at end of file diff --git a/model_validation_api/models.py b/model_validation_api/models.py index 4cb710cd3..7150c513a 100644 --- a/model_validation_api/models.py +++ b/model_validation_api/models.py @@ -164,7 +164,7 @@ class ValidationTestResult(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, ) model_version = models.ForeignKey(ScientificModelInstance) test_code = models.ForeignKey(ValidationTestCode) - results_storage = models.TextField(help_text="Location of data files produced by the test run") # or store locations of individual files? + results_storage = models.TextField(blank=True, help_text="Location of data files produced by the test run") # or store locations of individual files? score = models.FloatField(help_text="A numerical measure of the difference between model and experiment") # name this 'score'? like sciunit # should result be a Quantity? passed = models.NullBooleanField(help_text="Whether the test passed or failed") diff --git a/model_validation_api/validation_framework_toolbox/user_auth_functions.py b/model_validation_api/validation_framework_toolbox/user_auth_functions.py index 367c13e83..2f7ace542 100644 --- a/model_validation_api/validation_framework_toolbox/user_auth_functions.py +++ b/model_validation_api/validation_framework_toolbox/user_auth_functions.py @@ -217,10 +217,10 @@ def is_authorised(request, collab_id): if request.META.get("HTTP_AUTHORIZATION", None) == None : return False else: - if not (_is_collaborator_token(request, collab_id) or _is_collaborator_token(request, collab_id)): - return False - else: - return True + auth = _is_collaborator_token(request, collab_id) + if auth == False: + auth = _is_collaborator_token(request, admin_id) + return auth else : if not (_is_collaborator(request, collab_id) or _is_collaborator(request,admin_id)): diff --git a/model_validation_api/views.py b/model_validation_api/views.py index 12d27be10..845040069 100644 --- a/model_validation_api/views.py +++ b/model_validation_api/views.py @@ -493,6 +493,10 @@ def get(self, request, format=None, **kwargs): :type timestamp: datetime :param model_alias: alias of the model name :type model_alias: str + :param code_format: format of the code + :type code_format: str + :param hash: hash + :type hash: str :return: list of instances :rtype: dictionnary """ @@ -505,6 +509,8 @@ def get(self, request, format=None, **kwargs): param_source = request.GET.getlist('source') param_timestamp = request.GET.getlist('timestamp') param_model_alias = request.GET.getlist('model_alias') + param_code_format = request.GET.getlist('code_format') + param_hash = request.GET.getlist('hash') if check_list_uuid_validity(param_id) is False : return Response("Badly formed uuid in : id", status=status.HTTP_400_BAD_REQUEST) @@ -529,6 +535,10 @@ def get(self, request, format=None, **kwargs): q = q.filter(source__in = param_source ) if len(param_timestamp) > 0 : q = q.filter(timestamp__in = param_timestamp ) + if len(param_code_format) > 0 : + q = q.filter(code_format__in = param_code_format ) + if len(param_hash) > 0 : + q = q.filter(hash__in = param_hash ) instances = q @@ -749,7 +759,6 @@ def get(self, request, format=None, **kwargs): image_serializer = ScientificModelImageSerializer(data=images, context=serializer_context, many=True) image_serializer.is_valid() # needed.... - return Response({ 'images': image_serializer.data, }) @@ -771,7 +780,10 @@ def post(self, request, format=None): serializer = ScientificModelImageSerializer(data=image, context=serializer_context) if serializer.is_valid(): #security - app_id = ScientificModel.objects.get(id=image['model_id']).app_id + try: + app_id = ScientificModel.objects.get(id=image['model_id']).app_id + except: + app_id = ScientificModel.objects.get(alias=image['model_alias']).app_id collab_id = get_collab_id_from_app_id(app_id) if not is_authorised(request, collab_id): return HttpResponseForbidden() @@ -783,7 +795,12 @@ def post(self, request, format=None): serializer = ScientificModelImageSerializer(data=image, context=serializer_context) if serializer.is_valid(): - im = serializer.save(model_id=image['model_id']) + if image['model_id']: + im = serializer.save(model_id=image['model_id']) + else: + if image['model_alias']: + model_id = ScientificModel.objects.get(alias=image['model_alias']).id + im = serializer.save(model_id=model_id) list_id.append(im.id) @@ -1087,12 +1104,12 @@ def get(self, request, format=None, **kwargs): try: web_app = request.GET.getlist('web_app') except: - web_app = False + web_app = False id =id[0] models = ScientificModel.objects.filter(id=id) if len(models) > 0 : - + #check if private if models.values("private")[0]["private"] == 1 : #if private check if collab member diff --git a/validation_service/app/js/controller.js b/validation_service/app/js/controller.js index 9382241be..c6e64e2c6 100644 --- a/validation_service/app/js/controller.js +++ b/validation_service/app/js/controller.js @@ -50,6 +50,7 @@ testApp.controller('HomeCtrl', ['$scope', '$rootScope', '$http', '$location', "S var status = DataHandler.getCurrentStatus(); if (status != "up_to_date") { + console.log("status") DataHandler.loadModelsByPage($scope.app_id, $scope.nb_pages); } }); @@ -72,12 +73,14 @@ testApp.controller('HomeCtrl', ['$scope', '$rootScope', '$http', '$location', "S if (state_type == "model") { Context.validation_goToModelDetailView(element); + $scope.$apply(); } else if (state_type == "test") { Context.validation_goToTestDetailView(element); + $scope.$apply(); } else if (state_type == "result") { Context.validation_goToResultDetailView(element); + $scope.$apply(); } - } }); } @@ -1040,6 +1043,7 @@ ModelCatalogApp.filter('filterMultiple', ['$parse', '$filter', function($parse, if (!angular.isArray(items)) { return items; } + var filterObj = { data: items, filteredData: [], @@ -1059,9 +1063,15 @@ ModelCatalogApp.filter('filterMultiple', ['$parse', '$filter', function($parse, if (angular.isDefined(obj[i]['value'])) { fObj[key] = obj[i]['value']; } else { - fObj[key] = obj[i]; + if (key == 'collab_id') { //specific for Model Catalog home: to allow filter by collab (deep filter) + fObj['app'] = {} + fObj['app'][key] = obj[i]; + } else { + fObj[key] = obj[i]; + } } fData = fData.concat($filter('filter')(this.filteredData, fObj)); + } } } @@ -1084,7 +1094,6 @@ ModelCatalogApp.filter('filterMultiple', ['$parse', '$filter', function($parse, filterObj.applyFilter(obj, key); }); } - return filterObj.filteredData; } }]); @@ -1118,8 +1127,20 @@ ModelCatalogApp.controller('ModelCatalogCtrl', [ return models } + $scope._get_collab_and_app_ids_from_models = function() { + for (var i in $scope.models.models) { + if ($scope.models.models[i].app != null) { + if ($scope.collab_ids_to_select.indexOf($scope.models.models[i].app.collab_id.toString()) == -1) { + $scope.collab_ids_to_select.push($scope.models.models[i].app.collab_id.toString()); + } + } + } + $scope.$apply(); + } + $scope.$on('models_updated', function(event, models) { $scope.models = $scope._change_empty_organization_string(models); + $scope.collab_ids_to_select = $scope._get_collab_and_app_ids_from_models(); }); Context.setService().then(function() { @@ -1164,8 +1185,9 @@ ModelCatalogApp.controller('ModelCatalogCtrl', [ $scope.collab_cell_type = CollabParameters.getParametersOrDefaultByType("cell_type"); $scope.collab_model_type = CollabParameters.getParametersOrDefaultByType("model_type"); $scope.collab_organization = CollabParameters.getParametersOrDefaultByType("organization"); - - + $scope.collab_ids_to_select = new Array(); + $scope._get_collab_and_app_ids_from_models(); + // $scope.selected_collab = $scope.collab_ids_to_select //initialize $scope.is_collab_member = false; diff --git a/validation_service/app/js/service.js b/validation_service/app/js/service.js index de1a7e60b..12840b6e0 100644 --- a/validation_service/app/js/service.js +++ b/validation_service/app/js/service.js @@ -450,7 +450,7 @@ DataHandlerServices.service('DataHandler', ['$rootScope', 'ScientificModelRest', } else { var temp_models = ScientificModelRest.get(dict_params); temp_models.$promise.then(function() { - models = { date_last_load: new Date(), status: "up_to_date", data: temp_models }; + models = { date_last_load: new Date(), status: "loading", data: temp_models }; resolve(models.data, models.status); }); } @@ -474,7 +474,7 @@ DataHandlerServices.service('DataHandler', ['$rootScope', 'ScientificModelRest', $rootScope.$broadcast('models_updated', models.data); //change status if last load is done - if (pages_loaded.length == nb_pages.length) { + if (pages_loaded.length == nb_pages) { models.date_last_load = new Date(); models.status = "up_to_date"; } diff --git a/validation_service/app/templates/model_catalog/model-catalog.tpl.html b/validation_service/app/templates/model_catalog/model-catalog.tpl.html index 63287b319..947fbae8f 100644 --- a/validation_service/app/templates/model_catalog/model-catalog.tpl.html +++ b/validation_service/app/templates/model_catalog/model-catalog.tpl.html @@ -8,9 +8,7 @@

Model Catalog

@@ -58,8 +68,9 @@

Model Catalog

- + {{ model.name}} {{ model.alias }} {{ model.species }} diff --git a/validation_service/app/templates/validation_framework/validation_test_result_detail.tpl.html b/validation_service/app/templates/validation_framework/validation_test_result_detail.tpl.html index 0f1ce420f..8d5e069f9 100644 --- a/validation_service/app/templates/validation_framework/validation_test_result_detail.tpl.html +++ b/validation_service/app/templates/validation_framework/validation_test_result_detail.tpl.html @@ -240,9 +240,8 @@

Storage

-
- +