From de0acf4ea9bfca6f430c17421e6ddb8dca84f10b Mon Sep 17 00:00:00 2001 From: fredkingham Date: Fri, 15 Jul 2016 13:33:41 +0100 Subject: [PATCH 1/4] removed the multisave step --- pathway/pathways.py | 25 +--------- .../js/pathway/controllers/multi_save.js | 47 ------------------- pathway/static/js/pathway/directives.js | 9 ++-- .../js/pathway/services/multi_stage_form.js | 6 ++- pathway/templates/_helpers/multisave.html | 2 +- pathway/templates/pathway/multi_save.html | 17 +------ pathway/tests/test_template_tags.py | 4 +- 7 files changed, 13 insertions(+), 97 deletions(-) diff --git a/pathway/pathways.py b/pathway/pathways.py index 39964e4..77c8a48 100644 --- a/pathway/pathways.py +++ b/pathway/pathways.py @@ -1,17 +1,12 @@ import inspect -from copy import copy from functools import wraps from django.core.urlresolvers import reverse -from django.conf import settings from django.db import models, transaction from django.utils.text import slugify -from django.http import Http404 from opal.core import discoverable -from opal.models import Patient, Episode, EpisodeSubrecord -from opal.utils import stringport -from opal.utils import _itersubclasses +from opal.models import Patient, Episode def extract_pathway_field(some_fun): @@ -72,24 +67,6 @@ def pre_save(self, data, user): pass -class MultSaveStep(Step): - def to_dict(self): - result = super(MultSaveStep, self).to_dict() - - if "template_url" not in self.other_args: - result["template_url"] = "/templates/pathway/multi_save.html" - - if "controller_class" not in self.other_args: - result["controller_class"] = "MultiSaveCtrl" - - result["model_form_url"] = self.model.get_form_url() - - result["record_url"] = reverse( - "record_view", kwargs=dict(model=self.model.get_api_name()) - ), - return result - - class RedirectsToPatientMixin(object): def redirect_url(self, patient): return "/#/patient/{0}".format(patient.id) diff --git a/pathway/static/js/pathway/controllers/multi_save.js b/pathway/static/js/pathway/controllers/multi_save.js index 06e9a31..8b13789 100644 --- a/pathway/static/js/pathway/controllers/multi_save.js +++ b/pathway/static/js/pathway/controllers/multi_save.js @@ -1,48 +1 @@ -angular.module('opal.controllers').controller('MultiSaveCtrl', - function(Options, $controller, step, scope, episode) { - "use strict"; - var vm = this; - var parentCtrl = $controller("MultistageDefault"); - _.extend(vm, parentCtrl); - - vm.step = step; - vm.multipleModels = []; - - vm.cleanModel = function(editing_field){ - _.each(_.keys(editing_field), function(a){ - editing_field[a] = undefined; - }); - }; - - if(episode && episode[step.api_name].length > 1){ - vm.multipleModels = angular.copy(episode[step.api_name]); - var editing_field = scope.editing[step.api_name]; - vm.cleanModel(editing_field); - } - - vm.isClean = function(editing_field){ - return !_.some(_.values(editing_field)); - }; - - vm.addAnother = function(){ - var editing_field = scope.editing[step.api_name]; - - if(!vm.isClean(editing_field)){ - vm.multipleModels.push(angular.copy(editing_field)); - vm.cleanModel(editing_field); - } - }; - - vm.remove = function($index){ - vm.multipleModels.splice($index, 1); - }; - - vm.preSave = function(editing){ - var all_models = angular.copy(vm.multipleModels); - if(!vm.isClean(editing[step.api_name])){ - all_models.push(editing[step.api_name]); - } - editing[step.api_name] = all_models; - }; -}); diff --git a/pathway/static/js/pathway/directives.js b/pathway/static/js/pathway/directives.js index 2f7dbfa..1afc7f1 100644 --- a/pathway/static/js/pathway/directives.js +++ b/pathway/static/js/pathway/directives.js @@ -4,6 +4,8 @@ directives.directive("saveMultiple", function($parse, $rootScope, Referencedata) return { scope: { parentModel: "=saveMultiple", + form_url: "=?saveMultipleFormUrl", + display_name: "=?saveMultipleLabel" }, templateUrl: "/templates/pathway/save_multiple.html", link: function(scope, element, attrs){ @@ -26,15 +28,12 @@ directives.directive("saveMultiple", function($parse, $rootScope, Referencedata) } var requiredAttrs = { - "form_url": "saveMultipleformUrl", + "form_url": "saveMultipleFormUrl", "display_name": "saveMultipleLabel" }; _.each(requiredAttrs, function(jsName, schemaName){ - if(attrs[jsName]){ - scope[schemaName] = attrs[jsName]; - } - else{ + if(!scope[schemaName]){ scope[schemaName] = getSchemaField(schemaName); } }); diff --git a/pathway/static/js/pathway/services/multi_stage_form.js b/pathway/static/js/pathway/services/multi_stage_form.js index 24bb507..f57b395 100644 --- a/pathway/static/js/pathway/services/multi_stage_form.js +++ b/pathway/static/js/pathway/services/multi_stage_form.js @@ -61,8 +61,8 @@ angular.module('opal.services').provider('multistage', function(){ var editing = angular.copy(createdScope.editing); _.each(steps, function(step){ - if(step.controller.preSave){ - step.controller.preSave(editing); + if(step.scope.preSave){ + step.scope.preSave(editing); } }); @@ -117,6 +117,8 @@ angular.module('opal.services').provider('multistage', function(){ } _.each(scope.steps, function(step){ var stepScope = scope.$new(); + // always put the step on the scope + stepScope.step = step; if(step.controller_class){ step.controller = $controller(step.controller_class, { step: step, diff --git a/pathway/templates/_helpers/multisave.html b/pathway/templates/_helpers/multisave.html index 1fca506..3408f63 100644 --- a/pathway/templates/_helpers/multisave.html +++ b/pathway/templates/_helpers/multisave.html @@ -1 +1 @@ -
+
diff --git a/pathway/templates/pathway/multi_save.html b/pathway/templates/pathway/multi_save.html index 5a9251c..82124e9 100644 --- a/pathway/templates/pathway/multi_save.html +++ b/pathway/templates/pathway/multi_save.html @@ -1,16 +1 @@ -
-
-
-
-
-
- -
-
-
- -
- -
+
diff --git a/pathway/tests/test_template_tags.py b/pathway/tests/test_template_tags.py index e52a571..67eeef0 100644 --- a/pathway/tests/test_template_tags.py +++ b/pathway/tests/test_template_tags.py @@ -13,8 +13,8 @@ def test_with_model(self, get_form_url): rendered = template.render(Context(models)) self.assertIn('save-multiple="editing.colour"', rendered) self.assertIn( - 'save-multiple-form-url="/templates/forms/colour.html"', rendered + 'save-multiple-form-url="\'/templates/forms/colour.html\'"', rendered ) self.assertIn( - 'save-multiple-label="Colour"', rendered + 'save-multiple-label="\'Colour\'"', rendered ) From a2201ea6740d3762284211aafc5ca6afcea675b6 Mon Sep 17 00:00:00 2001 From: fredkingham Date: Fri, 15 Jul 2016 13:40:43 +0100 Subject: [PATCH 2/4] don't reinitialise opal directives --- pathway/static/js/pathway/directives.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/pathway/static/js/pathway/directives.js b/pathway/static/js/pathway/directives.js index 1afc7f1..1c6f47e 100644 --- a/pathway/static/js/pathway/directives.js +++ b/pathway/static/js/pathway/directives.js @@ -1,5 +1,3 @@ -var directives = angular.module('opal.directives', []); - directives.directive("saveMultiple", function($parse, $rootScope, Referencedata){ return { scope: { From ae02b7006a66a9889b0c9b67ee3b99b220f917e8 Mon Sep 17 00:00:00 2001 From: fredkingham Date: Fri, 15 Jul 2016 15:41:07 +0100 Subject: [PATCH 3/4] fixes for preexisting models, updated directves and templates to allow multisave steps to be declared in the template, updated the read me --- README.md | 27 ++++++++++++++--------- pathway/pathways.py | 5 +++++ pathway/static/js/pathway/directives.js | 18 ++++++++++----- pathway/templates/pathway/multi_save.html | 2 +- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 73e5d18..7cf014d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,23 @@ class SimplePathway(pathways.Pathway): ) ``` +If we want to save multiple types of models on the same page, a step needs a title, +an icon and a template url, that's all. Then in the template you can just insert the forms off the models +e.g. +```html +{% include models.Demographics.get_form_template %} +{% include models.Diagnosis.get_form_template %} +``` + +if we want to also save multiple types of the same model e.g. treatment on this page we can add in a multi save section +using the 'multisave' template tag, then our page will look something like this + +```html +{% include models.Demographics.get_form_template %} +{% include models.Diagnosis.get_form_template %} +{% multisave models.Treatment %} +``` + ### Success redirects Often, after successfully saving a pathway, we want to redirect the user to a different @@ -160,13 +177,3 @@ Redirect to the patient detail page for this patient. ## pathways.RedirectsToEpisodeMixin Redirect to the patient detail page, viewing the last episode for this patient. - -## Template tags - -Pathways allow you to do things that aren't usually trivial including saving multiple models -at the same time, to make this easy we have a template tag that you can add, this will add -forms for each of your existing models and allow the user to add new models dynamically - -```html -{% multisave models.Treatment %} -``` diff --git a/pathway/pathways.py b/pathway/pathways.py index 77c8a48..be06786 100644 --- a/pathway/pathways.py +++ b/pathway/pathways.py @@ -67,6 +67,11 @@ def pre_save(self, data, user): pass +class MultSaveStep(Step): + def template_url(self): + return "/templates/pathway/multi_save.html" + + class RedirectsToPatientMixin(object): def redirect_url(self, patient): return "/#/patient/{0}".format(patient.id) diff --git a/pathway/static/js/pathway/directives.js b/pathway/static/js/pathway/directives.js index 1c6f47e..5e13afa 100644 --- a/pathway/static/js/pathway/directives.js +++ b/pathway/static/js/pathway/directives.js @@ -3,13 +3,17 @@ directives.directive("saveMultiple", function($parse, $rootScope, Referencedata) scope: { parentModel: "=saveMultiple", form_url: "=?saveMultipleFormUrl", - display_name: "=?saveMultipleLabel" + display_name: "=?saveMultipleLabel", + model_name: "=?saveMultipleModelName" }, templateUrl: "/templates/pathway/save_multiple.html", link: function(scope, element, attrs){ var editingString = attrs.saveMultiple; - var model = editingString.substr(editingString.indexOf(".")+1); - var getModel = $parse(model); + + if(!scope.model_name){ + scope.model_name = editingString.substr(editingString.indexOf(".")+1); + } + var getModel = $parse(scope.model_name); // hopefully we can do this nicer in future Referencedata.then(function(referencedata){ @@ -22,7 +26,7 @@ directives.directive("saveMultiple", function($parse, $rootScope, Referencedata) if(!fields){ throw "fields not loaded"; } - return fields[model][name]; + return fields[scope.model_name][name]; } var requiredAttrs = { @@ -47,7 +51,11 @@ directives.directive("saveMultiple", function($parse, $rootScope, Referencedata) // shallow copy not deep copy as angular copy can't // deal with moments - scope.model = {'allModels': _.clone(scope.parentModel)}; + scope.model = {'allModels': _.map(scope.parentModel, function(row){ + var result = {}; + result[scope.model_name] = row; + return result; + })}; scope.remove = function($index){ scope.model.allModels.splice($index, 1); diff --git a/pathway/templates/pathway/multi_save.html b/pathway/templates/pathway/multi_save.html index 82124e9..94e3f6d 100644 --- a/pathway/templates/pathway/multi_save.html +++ b/pathway/templates/pathway/multi_save.html @@ -1 +1 @@ -
+
From e61ae3ddabd4434b7fa6e01688aeca0799822c5f Mon Sep 17 00:00:00 2001 From: David Miller Date: Fri, 15 Jul 2016 16:53:05 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7cf014d..3a52ad1 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ class SimplePathway(pathways.Pathway): You could access this pathway from e.g. `http:\\localhost:8000\pathway\#\simples\`. +### Steps with multiple isntances of records Sometimes we may want to add multiple instances of a subrecord at the same time, for example when we're recording multiple allergies. To add a multiple step simply use a MultiSaveStep, for example: @@ -74,18 +75,43 @@ class SimplePathway(pathways.Pathway): ) ``` -If we want to save multiple types of models on the same page, a step needs a title, -an icon and a template url, that's all. Then in the template you can just insert the forms off the models -e.g. +### Complex steps - more than one subrecord type + +If we want to save multiple types of subrecords at the same step, we can do that by simply including the +relevant form templates in a custom step template. + +```python +from pathway import pathways +from myapp import models + +class SimplePathway(pathways.Pathway): + display_name = 'A simple pathway' + slug = 'simples' + steps = ( + pathways.Step( + title='Demographics and Diagnosis', + icon='fa fa-clock', + template='pathways/demographics_and_diagnosis_step.html' + ), + ) +``` + +The title and icon are rendered in the header for this step in your pathway, which exist outside the scope of the step template itself. Then all we would need is the template itself: + ```html + {% include models.Demographics.get_form_template %} {% include models.Diagnosis.get_form_template %} ``` -if we want to also save multiple types of the same model e.g. treatment on this page we can add in a multi save section -using the 'multisave' template tag, then our page will look something like this +#### Complex steps with multiple instances per subrecord + +If we need to also save multiple types of the same subrecord e.g. `Treatment` in this step, +we simply use the `multisave` template tag. ```html +{% load pathways %} + {% include models.Demographics.get_form_template %} {% include models.Diagnosis.get_form_template %} {% multisave models.Treatment %}