mirror of https://github.com/snachodog/mybuddy.git
Merge remote-tracking branch 'origin/master' into 333-en-gb-datetimeformat
This commit is contained in:
commit
f0a7f53752
|
@ -61,13 +61,10 @@ jobs:
|
||||||
deploy:
|
deploy:
|
||||||
needs: test
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
DEPLOY_DEMO: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
|
||||||
steps:
|
steps:
|
||||||
- if: ${{ env.DEPLOY_DEMO }}
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v2
|
- name: Deploy demo
|
||||||
- if: ${{ env.DEPLOY_DEMO }}
|
|
||||||
name: Deploy demo
|
|
||||||
uses: akhileshns/heroku-deploy@v3.12.12
|
uses: akhileshns/heroku-deploy@v3.12.12
|
||||||
with:
|
with:
|
||||||
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
|
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
|
||||||
|
|
|
@ -3,64 +3,90 @@ from django_filters import rest_framework as filters
|
||||||
from core import models
|
from core import models
|
||||||
|
|
||||||
|
|
||||||
class TimeFieldFilter(filters.FilterSet):
|
class ChildFieldFilter(filters.FilterSet):
|
||||||
date = filters.DateFilter(field_name='date', label='Date')
|
class Meta:
|
||||||
date_min = filters.DateFilter(field_name='time__date', label='Min. Date',
|
abstract = True
|
||||||
lookup_expr='gte')
|
fields = ['child']
|
||||||
|
|
||||||
|
|
||||||
|
class TimeFieldFilter(ChildFieldFilter):
|
||||||
|
date = filters.DateFilter(field_name='time__date', label='Date')
|
||||||
date_max = filters.DateFilter(field_name='time__date', label='Max. Date',
|
date_max = filters.DateFilter(field_name='time__date', label='Max. Date',
|
||||||
lookup_expr='lte')
|
lookup_expr='lte')
|
||||||
|
date_min = filters.DateFilter(field_name='time__date', label='Min. Date',
|
||||||
|
lookup_expr='gte')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
fields = sorted(ChildFieldFilter.Meta.fields + [
|
||||||
|
'date',
|
||||||
|
'date_max',
|
||||||
|
'date_min'
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class StartEndFieldFilter(filters.FilterSet):
|
class StartEndFieldFilter(ChildFieldFilter):
|
||||||
end = filters.DateFilter(field_name='end__date', label='End Date')
|
end = filters.DateFilter(field_name='end__date', label='End Date')
|
||||||
end_min = filters.DateFilter(field_name='end__date', label='Min. End Date',
|
|
||||||
lookup_expr='gte')
|
|
||||||
end_max = filters.DateFilter(field_name='end__date', label='Max. End Date',
|
end_max = filters.DateFilter(field_name='end__date', label='Max. End Date',
|
||||||
lookup_expr='lte')
|
lookup_expr='lte')
|
||||||
|
end_min = filters.DateFilter(field_name='end__date', label='Min. End Date',
|
||||||
|
lookup_expr='gte')
|
||||||
start = filters.DateFilter(field_name='start__date', label='Start Date')
|
start = filters.DateFilter(field_name='start__date', label='Start Date')
|
||||||
start_min = filters.DateFilter(field_name='start__date', lookup_expr='gte',
|
start_max = filters.DateFilter(field_name='start__date', lookup_expr='lte',
|
||||||
label='Min. Start Date',)
|
|
||||||
start_end = filters.DateFilter(field_name='start__date', lookup_expr='lte',
|
|
||||||
label='Max. End Date')
|
label='Max. End Date')
|
||||||
|
start_min = filters.DateFilter(field_name='start__date', lookup_expr='gte',
|
||||||
|
label='Min. Start Date')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
fields = sorted(ChildFieldFilter.Meta.fields + [
|
||||||
|
'end',
|
||||||
|
'end_max',
|
||||||
|
'end_min',
|
||||||
|
'start',
|
||||||
|
'start_max',
|
||||||
|
'start_min'
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeFilter(TimeFieldFilter):
|
class DiaperChangeFilter(TimeFieldFilter):
|
||||||
class Meta:
|
class Meta(TimeFieldFilter.Meta):
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
fields = ['child', 'wet', 'solid', 'color', 'amount']
|
fields = sorted(TimeFieldFilter.Meta.fields + [
|
||||||
|
'wet',
|
||||||
|
'solid',
|
||||||
|
'color',
|
||||||
|
'amount'
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class FeedingFilter(StartEndFieldFilter):
|
class FeedingFilter(StartEndFieldFilter):
|
||||||
class Meta:
|
class Meta(StartEndFieldFilter.Meta):
|
||||||
model = models.Feeding
|
model = models.Feeding
|
||||||
fields = ['child', 'type', 'method']
|
fields = sorted(StartEndFieldFilter.Meta.fields + ['type', 'method'])
|
||||||
|
|
||||||
|
|
||||||
class NoteFilter(TimeFieldFilter):
|
class NoteFilter(TimeFieldFilter):
|
||||||
class Meta:
|
class Meta(TimeFieldFilter.Meta):
|
||||||
model = models.Note
|
model = models.Note
|
||||||
fields = ['child']
|
|
||||||
|
|
||||||
|
|
||||||
class SleepFilter(StartEndFieldFilter):
|
class SleepFilter(StartEndFieldFilter):
|
||||||
class Meta:
|
class Meta(StartEndFieldFilter.Meta):
|
||||||
model = models.Sleep
|
model = models.Sleep
|
||||||
fields = ['child']
|
|
||||||
|
|
||||||
|
|
||||||
class TemperatureFilter(TimeFieldFilter):
|
class TemperatureFilter(TimeFieldFilter):
|
||||||
class Meta:
|
class Meta(TimeFieldFilter.Meta):
|
||||||
model = models.Temperature
|
model = models.Temperature
|
||||||
fields = ['child']
|
|
||||||
|
|
||||||
|
|
||||||
class TimerFilter(StartEndFieldFilter):
|
class TimerFilter(StartEndFieldFilter):
|
||||||
class Meta:
|
class Meta(StartEndFieldFilter.Meta):
|
||||||
model = models.Timer
|
model = models.Timer
|
||||||
fields = ['child', 'active', 'user']
|
fields = sorted(StartEndFieldFilter.Meta.fields + ['active', 'user'])
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeFilter(StartEndFieldFilter):
|
class TummyTimeFilter(StartEndFieldFilter):
|
||||||
class Meta:
|
class Meta(StartEndFieldFilter.Meta):
|
||||||
model = models.TummyTime
|
model = models.TummyTime
|
||||||
fields = ['child']
|
|
||||||
|
|
|
@ -11,4 +11,6 @@ class APIMetadata(metadata.SimpleMetadata):
|
||||||
data.pop('description')
|
data.pop('description')
|
||||||
if hasattr(view, 'filterset_fields'):
|
if hasattr(view, 'filterset_fields'):
|
||||||
data.update({'filters': view.filterset_fields})
|
data.update({'filters': view.filterset_fields})
|
||||||
|
elif hasattr(view, 'filterset_class'):
|
||||||
|
data.update({'filters': view.filterset_class.Meta.fields})
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -3,7 +3,7 @@ import time
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone, translation
|
||||||
from django.conf.locale.en import formats as formats_en_us
|
from django.conf.locale.en import formats as formats_en_us
|
||||||
from django.conf.locale.en_GB import formats as formats_en_gb
|
from django.conf.locale.en_GB import formats as formats_en_gb
|
||||||
|
|
||||||
|
@ -58,10 +58,6 @@ def update_en_gb_date_formats():
|
||||||
'%d/%m/%Y %I:%M %p', # '25/10/2006 2:30 PM'
|
'%d/%m/%Y %I:%M %p', # '25/10/2006 2:30 PM'
|
||||||
]
|
]
|
||||||
|
|
||||||
# Not setting this makes pages display using the the 25/10/2006 as desired
|
|
||||||
# Add custom "short" version of `MONTH_DAY_FORMAT`.
|
|
||||||
# formats_en_gb.SHORT_MONTH_DAY_FORMAT = 'j M'
|
|
||||||
|
|
||||||
# Append all other input formats from the base locale.
|
# Append all other input formats from the base locale.
|
||||||
formats_en_gb.DATETIME_INPUT_FORMATS = \
|
formats_en_gb.DATETIME_INPUT_FORMATS = \
|
||||||
custom_input_formats + formats_en_gb.DATETIME_INPUT_FORMATS
|
custom_input_formats + formats_en_gb.DATETIME_INPUT_FORMATS
|
||||||
|
@ -76,11 +72,29 @@ class UserLanguageMiddleware:
|
||||||
|
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
user = request.user
|
user = request.user
|
||||||
if hasattr(user, 'settings') and user.settings.language == 'en-US':
|
if hasattr(user, 'settings') and user.settings.language:
|
||||||
update_en_us_date_formats()
|
language = user.settings.language
|
||||||
elif hasattr(user, 'settings') and user.settings.language == 'en-GB':
|
elif request.LANGUAGE_CODE:
|
||||||
update_en_gb_date_formats()
|
language = request.LANGUAGE_CODE
|
||||||
return self.get_response(request)
|
else:
|
||||||
|
language = settings.LANGUAGE_CODE
|
||||||
|
|
||||||
|
if language:
|
||||||
|
if language == 'en-US':
|
||||||
|
update_en_us_date_formats()
|
||||||
|
elif language == 'en-GB':
|
||||||
|
update_en_gb_date_formats()
|
||||||
|
|
||||||
|
# Set the language before generating the response.
|
||||||
|
translation.activate(language)
|
||||||
|
|
||||||
|
response = self.get_response(request)
|
||||||
|
|
||||||
|
# Deactivate the translation before the response is sent so it not
|
||||||
|
# reused in other threads.
|
||||||
|
translation.deactivate()
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
class UserTimezoneMiddleware:
|
class UserTimezoneMiddleware:
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.contrib.auth.models import User
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
from django.utils import translation
|
||||||
from django.utils.text import format_lazy
|
from django.utils.text import format_lazy
|
||||||
from django.utils.translation import gettext as _, gettext_lazy
|
from django.utils.translation import gettext as _, gettext_lazy
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
@ -144,7 +145,9 @@ class UserSettings(LoginRequiredMixin, View):
|
||||||
user_settings = form_settings.save(commit=False)
|
user_settings = form_settings.save(commit=False)
|
||||||
user.settings = user_settings
|
user.settings = user_settings
|
||||||
user.save()
|
user.save()
|
||||||
|
translation.activate(user.settings.language)
|
||||||
messages.success(request, _('Settings saved!'))
|
messages.success(request, _('Settings saved!'))
|
||||||
|
translation.deactivate()
|
||||||
return set_language(request)
|
return set_language(request)
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'user_form': form_user,
|
'user_form': form_user,
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.urls import reverse
|
||||||
from django.utils import timezone, timesince
|
from django.utils import timezone, timesince
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from core.models import DiaperChange, Feeding, Sleep, TummyTime
|
from core.models import DiaperChange, Feeding, Note, Sleep, TummyTime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ def get_objects(date, child=None):
|
||||||
_add_feedings(min_date, max_date, events, child)
|
_add_feedings(min_date, max_date, events, child)
|
||||||
_add_sleeps(min_date, max_date, events, child)
|
_add_sleeps(min_date, max_date, events, child)
|
||||||
_add_tummy_times(min_date, max_date, events, child)
|
_add_tummy_times(min_date, max_date, events, child)
|
||||||
|
_add_notes(min_date, max_date, events, child)
|
||||||
|
|
||||||
events.sort(key=lambda x: x['time'], reverse=True)
|
events.sort(key=lambda x: x['time'], reverse=True)
|
||||||
|
|
||||||
|
@ -169,3 +170,18 @@ def _add_diaper_changes(min_date, max_date, events, child):
|
||||||
args=[instance.id]),
|
args=[instance.id]),
|
||||||
'model_name': instance.model_name
|
'model_name': instance.model_name
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def _add_notes(min_date, max_date, events, child):
|
||||||
|
instances = Note.objects.filter(
|
||||||
|
time__range=(min_date, max_date)).order_by('-time')
|
||||||
|
if child:
|
||||||
|
instances = instances.filter(child=child)
|
||||||
|
for instance in instances:
|
||||||
|
events.append({
|
||||||
|
'time': timezone.localtime(instance.time),
|
||||||
|
'details': [instance.note],
|
||||||
|
'edit_link': reverse('core:note-update',
|
||||||
|
args=[instance.id]),
|
||||||
|
'model_name': instance.model_name
|
||||||
|
})
|
||||||
|
|
|
@ -85,7 +85,7 @@ documentation section: [Translation](https://docs.djangoproject.com/en/3.0/topic
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- Python 3.6+, pip, pipenv
|
- Python 3.6+, pip, pipenv
|
||||||
- NodeJS 14.x and NPM 7.x
|
- NVM (NodeJS 14.x and NPM 7.x)
|
||||||
- Gulp
|
- Gulp
|
||||||
- Possibly `libpq-dev`
|
- Possibly `libpq-dev`
|
||||||
- This is necessary if `psycopg2` can't find an appropriate prebuilt binary.
|
- This is necessary if `psycopg2` can't find an appropriate prebuilt binary.
|
||||||
|
@ -96,13 +96,21 @@ documentation section: [Translation](https://docs.djangoproject.com/en/3.0/topic
|
||||||
|
|
||||||
1. Install required Python packages, including dev packages
|
1. Install required Python packages, including dev packages
|
||||||
|
|
||||||
pipenv install --three
|
pipenv install --three --dev
|
||||||
|
|
||||||
- If this fails, install `libpq-dev` (e.g. `sudo apt install libpq-dev`) and try again.
|
- If this fails, install `libpq-dev` (e.g. `sudo apt install libpq-dev`) and try again.
|
||||||
|
|
||||||
|
1. Installed Node 14.x (if necessary)
|
||||||
|
|
||||||
|
nvm install 14
|
||||||
|
|
||||||
|
1. Activate Node 14.x
|
||||||
|
|
||||||
|
nvm use
|
||||||
|
|
||||||
1. Install Gulp CLI
|
1. Install Gulp CLI
|
||||||
|
|
||||||
sudo npm install -g gulp-cli
|
npm install -g gulp-cli
|
||||||
|
|
||||||
1. Install required Node packages
|
1. Install required Node packages
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ python3 /app/babybuddy/manage.py clearsessions
|
||||||
|
|
||||||
## Heroku
|
## Heroku
|
||||||
|
|
||||||
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
|
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://dashboard.heroku.com/new?button-url=https%3A%2F%2Fgithub.com%2Fbabybuddy%2Fbabybuddy&template=https%3A%2F%2Fgithub.com%2Fbabybuddy%2Fbabybuddy)
|
||||||
|
|
||||||
For manual deployments to Heroku without using the "deploy" button, make sure to
|
For manual deployments to Heroku without using the "deploy" button, make sure to
|
||||||
create the following settings before pushing:
|
create the following settings before pushing:
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1 +1 @@
|
||||||
python-3.9.8
|
python-3.9.9
|
Loading…
Reference in New Issue