Skip to content

Commit

Permalink
Merge branch 'v0.17.0' into dependabot/pip/jinja2-2.10.1
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmiller committed Aug 9, 2019
2 parents 69bbcd1 + 9d20e70 commit cb6dda8
Show file tree
Hide file tree
Showing 36 changed files with 333 additions and 70 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: python
dist: trusty
python:
- "3.5"
- "3.6"
Expand Down
32 changes: 32 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
### 0.17.0 (Major Release)

#### Javascript API removals

* Removes the function Episode.isDischarged() (This was rarely if ever used, and no longer an accurate represenation of dischargedness.)

#### Miscelanious changes

Bumps Flake8 version to 3.7.8 - new code will now be required to pass flake8 v3.7.8

#### Updates to the Dependency Graph

* Psycopg2: 2.7.6.1 -> 2.8.3

### 0.16.0 (Major Release)

Adds serialize_date, serialize_datetime, serialize_time utility functions to serialize date/datetime/time to
strings.

Diagnosis.details is now a text field.

Changes the requirements.txt files that get created when we create an opal application or plugin to use `python-dateutil==2.7.5`

### 0.15.0 (Major Release)

Adds an optional setting OPAL_DEFAULT_SEARCH_FIELDS that specifies the fields used to
search in when a criteria isn't specified.

### 0.14.2 (Minor Release)

Documentation fix, we're on python 3.4 now.

### 0.14.1 (Minor Release)

The search plugin was not excluding search strings from analytics.
Expand Down
6 changes: 3 additions & 3 deletions doc/docs/guides/archetypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ frequency | FKorFT(Drugfreq)

### Diagnosis

Field|Type|Length
-----|----|---
Field|Type
-----|----
condition | FKorFT(Condition)
provisional | Boolean
details | Char | 255
details | Text
date_of_diagnosis | Date

### PastMedicalHistory
Expand Down
2 changes: 1 addition & 1 deletion doc/docs/guides/components_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Opal applications will typically be made up of several types of components.

![Layers of an Opal application](../img/OpalLayers.png)
![Layers of an Opal application](/img/OpalLayers.png)

### Opal

Expand Down
4 changes: 2 additions & 2 deletions doc/docs/guides/context_processors.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ All Opal settings are copied into the context of the template.

### Models

All [subrecords](../reference/subrecords/) (the underlying clinical models of Opal) are copied into the context of the template context and can be accessed from the variable `models`, e.g. the Allergies subrecord can be referred to by
All [subrecords](../reference/subrecords.md) (the underlying clinical models of Opal) are copied into the context of the template context and can be accessed from the variable `models`, e.g. the Allergies subrecord can be referred to by

```html
{{ models.Allergy }}
```

### Pathways

Pathways are copied in to the context of the template and can be accessed from the variable `pathways`. For an example Pathway you would be able to access attributes of a Pathway thus:
Pathways are copied in to the context of the template and can be accessed from the variable `pathways`. For an example Pathway you would be able to access attributes of a Pathway thus:

```html
{{ pathways.MyPathway.get_display_name }}
Expand Down
2 changes: 1 addition & 1 deletion doc/docs/guides/datamodel.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ implement a Demographics `Subrecord` as follows:

Subrecords also define various properties that will provide metadata about their
display or structure, which are documented in the
[Subrecord reference material](/reference/subrecords/)
[Subrecord reference material](../reference/subrecords.md)

### Core Clinical Data Model

Expand Down
4 changes: 2 additions & 2 deletions doc/docs/guides/episodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ More detail on customising the rest of the detail tempalte is found in the detai
## Default Category

The default category of episodes in an Opal application is set by the
[OpalApplication](../reference/opal_application) object's default_episode_category
[OpalApplication](../reference/opal_application.md) object's default_episode_category
property.

```python
Expand All @@ -62,7 +62,7 @@ class Application(application.OpalApplication):

## Defining your own EpisodeCategory

As EpisodeCategory is a [discoverable](discoverable) we can define our own to
As EpisodeCategory is a [discoverable](discoverable.md) we can define our own to
meet custom requirements.

Episode categories should be defined in a file named `episode_categories` of
Expand Down
2 changes: 1 addition & 1 deletion doc/docs/guides/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ forms, with less verbose templates.
</form>


For full documentation of the options, please see the [Form templatetags reference material](/reference/form_templatetags/)
For full documentation of the options, please see the [Form templatetags reference material](../reference/form_templatetags.md)
24 changes: 24 additions & 0 deletions doc/docs/reference/core_serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

Helpers for serializing and deserializing data

## `serialize_date(value)`
Given a date, serialize it to a string using the
`settings.DATE_FORMAT`

```python
as_date_str = serialize_date(datetime.date(2019, 4, 1))
```

## `serialize_datetime(value)`
Given a datetime, serialize it to a string using the
`settings.DATETIME_FORMAT`

```python
as_datetime_str = serialize_datetime(datetime.datetime(2019, 4, 1, 10, 30))
```

## `serialize_time(value)`
Given a time, serialize it to a string using the
`settings.TIME_FORMAT`

```python
as_datetime_str = serialize_time(datetime.time(10, 30))
```

## `deserialize_datetime(value)`

Given a string which represents a date time, deserialize it to a Python datetime
Expand Down
2 changes: 1 addition & 1 deletion doc/docs/reference/opal_application.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Returns the application class for the currently active application.

#### get_all_components

Returns an iterator of all the of the [plugins](/guides/plugins/) and the current application
Returns an iterator of all the of the [plugins](../guides/plugins.md) and the current application

## OpalApplication

Expand Down
12 changes: 12 additions & 0 deletions doc/docs/reference/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ The human readable form of your application name.
Displayed in the header by default.
Scaffolded applications start with whatever is passed in to `opal startproject`.

## OPAL_DEFAULT_SEARCH_FIELDS

Search fields that we look in by default when a user enters a search term.
Defaults to
```python
[
"demographics__hospital_number",
"demographics__first_name",
"demographics__surname"
]
```

## OPAL_LOG_OUT_DURATION

Opal will log users out if they have been inactive for greater than this value.
Expand Down
7 changes: 7 additions & 0 deletions doc/docs/reference/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
This document provides instructions for specific steps required to upgrading your Opal
application to a later version where there are extra steps required.

#### v0.15.0 -> v0.16.0
Diagnosis.details is now a text field. Please make and run migrations if you are
using it in your app.

The record template for diagnosis now shows the details on the next row.


### 0.13.1 -> 0.14.0
If you were creating a UserProfile, this will now fail as a UserProfile is created automatically after creating a user (by a signal).

Expand Down
16 changes: 8 additions & 8 deletions doc/docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Let's have a look at what that created for you:
urls.py # Django Urlconf
wsgi.py

patient_lists.py # these create the [lists](/guides/list_views/) for you application
patient_lists.py # these create the [lists](guides/list_views.md) for you application

assets/ # Your static files directory
templates/ # Your template directory
Expand Down Expand Up @@ -88,16 +88,16 @@ front-end Angular single page apps.
Most clinical services will need at some stage to generate a list of patients - so Opal provides
this functionality enabled by default.

The [list view](/guides/list_views/) is a spreadsheet-style list of patients - try navigating
to the list view and adding a patient with the `add patient` button.
The [list view](guides/list_views.md) is a spreadsheet-style list of patients - try navigating
to the list view and adding a patient with the `add patient` button. [episode](guides/datamodel.md)

<img src="/img/tutorial-list.png" width="600" style="margin: 12px auto; border: 1px solid black;"/>

Each column contains a different type of information about a patient, while each
row represents one patient.

<blockquote><small>
Strictly speaking each row is an <a href="/guides/datamodel/">episode</a>
Strictly speaking each row is an <a href="../guides/datamodel.md">episode</a>
of care for a patient - but we'll come to that in a second.
</small></blockquote>

Expand All @@ -120,7 +120,7 @@ class Diagnosis(EpisodeSubrecord):

You will notice that the condition field has a custom field type - `ForeignKeyOrFreeText`.
This is a custom field type that we use with Opal when we want to use a
[Lookup List](/guides/referencedata/).
[Lookup List](guides/referencedata.md).


Lookup Lists allow us to reference canonical lists of available terminology as a foreign key, while
Expand All @@ -147,7 +147,7 @@ For more details consult the
So far we've begun to get a sense of the batteries-included parts of Opal,
but before long, you're going to need to create models for your own needs.

Most Opal models are [Subrecords](/guides/datamodel/) - they relate to either a patient, or
Most Opal models are [Subrecords](guides/datamodel.md) - they relate to either a patient, or
an episode (an episode is for example, an admission to hospital).

Let's see how that works by creating a TODO list model that is assigned to
Expand Down Expand Up @@ -263,7 +263,7 @@ application.

For us, you'll notice that the value of `TODOItem.completed` simply displays as false -
which is not particularly useful. So let's update that using the Opal
[Boxed filter](/reference/javascript/javascript_helpers/#boxed). In `mynewapp/templates/records/todo_item.html`
[Boxed filter](../reference/javascript/javascript_helpers/#boxed). In `mynewapp/templates/records/todo_item.html`
change the last `span` to look like this:

```html
Expand Down Expand Up @@ -312,4 +312,4 @@ in your application. You can inspect these APIs interactively at the url:
### What next?

This is just a glimpse at the full range of functionality that comes with Opal - there is
much more to discover in the [Topic Guides](/guides/topic-guides/).
much more to discover in the [Topic Guides](guides/topic-guides.md).
2 changes: 1 addition & 1 deletion doc/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ dev_addr: 0.0.0.0:8965
include_next_prev: false

extra:
version: v0.14.0
version: v0.17.0

markdown_extensions:
- fenced_code
2 changes: 1 addition & 1 deletion opal/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Declare our current version string
"""
__version__ = '0.14.1'
__version__ = '0.17.0'
23 changes: 18 additions & 5 deletions opal/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ class UserProfileInline(admin.StackedInline):
filter_horizontal = ('roles',)


class FilterInline(admin.StackedInline):
model = models.Filter


class UserProfileAdmin(UserAdmin):
add_fieldsets = (
(None, {
Expand All @@ -42,7 +38,7 @@ class UserProfileAdmin(UserAdmin):
)
}),
)
inlines = [UserProfileInline, FilterInline, ]
inlines = [UserProfileInline]

def get_actions(self, request):
actions = super(UserProfileAdmin, self).get_actions(request)
Expand All @@ -63,6 +59,23 @@ def has_delete_permission(self, request, obj=None):
return False
return True

def save_formset(self, request, form, formset, change):
"""
The user profile is already created by a signal so
attatch the existing user profile if after the user
has been saved.
"""
if change:
super().save_formset(request, form, formset, change)
else:
instances = formset.save(commit=False)
profile = UserProfile.objects.get(user_id=form.instance.id)
for i in instances:
i.id = profile.id
i.user = profile.user
i.save()
formset.save_m2m()


class MyAdmin(VersionAdmin):
pass
Expand Down
2 changes: 1 addition & 1 deletion opal/core/patient_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def for_list(klass, patient_list):
if not issubclass(patient_list, PatientList):
raise ValueError(msg)
except TypeError:
raise ValueError(msg)
raise ValueError(msg)

for group in klass.list():
if patient_list in group.get_member_lists():
Expand Down
23 changes: 23 additions & 0 deletions opal/core/search/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,29 @@ def test_with_multiple_patient_episodes(self):
}
self.assertEqual(response, expected)

@patch('opal.core.search.views.PAGINATION_AMOUNT', 2)
def test_patients_more_than_pagination_amount(self):
"""
Prior to 0.16.0 the implementation would sometimes
return results with fewer than the number of results
that should have been on that page.
This is because a subquery was paginating by the
number of episodes rather than the number of
patients.
"""
blofeld_patient, blofeld_episode = self.create_patient(
"Ernst", "Blofeld", "23422"
)
blofeld_patient.create_episode()

response = json.loads(
self.get_response(
'{}/?query=o'.format(self.url)
).content.decode('UTF-8')
)
self.assertEqual(len(response["object_list"]), 2)


class SearchTemplateTestCase(OpalTestCase):

Expand Down
3 changes: 2 additions & 1 deletion opal/core/search/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ def simple_search_view(request):
# on postgres it blows up if we don't manually manage this
if not paginated_patients:
paginated_patients = models.Patient.objects.none()

episodes = models.Episode.objects.filter(
id__in=paginated_patients.values_list("episode__id", flat=True)
patient__in=paginated_patients
)
paginated["object_list"] = query.get_aggregate_patients_from_episodes(
episodes
Expand Down

0 comments on commit cb6dda8

Please sign in to comment.