Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic, user customizable events #217

Open
philip-n opened this issue May 26, 2021 · 7 comments
Open

Generic, user customizable events #217

philip-n opened this issue May 26, 2021 · 7 comments
Labels
enhancement Feature requests or improvements to existing functionality help wanted Issues where maintainers could use assistance from others

Comments

@philip-n
Copy link

Browsing through the issues, there are multiple requests for specific additional tasks/things to keep track of (medication, baby height, ...).

Most of them have almost the same requirements:

  • a name of the task
  • some default fields (pretty much always identical)
    • start date (or simply: date)
    • optional end date
    • note
  • some more custom-y fields that can be relevant
    • a quantity
    • potentially additional convenience features:
      • multiple choice / dropdown style selection between predefined values
      • named boolean values that are displayed as toggle-buttons (to allow quick input like fluid vs. hard with the diaper change)

Rather than implementing explicit models for all of the requested features, I'd propose adding a generic CustomEvent model that offers the generic fields listed above. The user could then first add the tasks they want to track in an admin menu and potentially define which of the available fields are relevant. These tasks would then be available in the frontend as usual, maybe under a new "custom tasks" item.

In my opinion, this would significantly extend the functionality (what you can jot down on a piece of paper, you could then also track in Baby Buddy) without bloating the interface with various things that some users might never care about (as it only offers what you configured).

Also, having everything in the same model would make it easy(-ish) for example to extend the sleep pattern style view to display additional tracked things.

Thoughts? Opinions?

@philip-n
Copy link
Author

To add some links to relevant issues:

@cdubz
Copy link
Member

cdubz commented May 27, 2021

This is an interesting idea. I certainly would not be opposed to it. This is kind of how I envision the "Notes" model right now so maybe we could just expand on that...

If this generic model itself is configurable (as you outline in the "some more custom-y fields that can be relevant" list) that will definitely ramp up the complexity both from a maintenance and UX perspective. It would be nice if we could, as you say, identify some of these common factors and then maybe add just one system-wide configurable field "category" (or something) that would be a select list on the generic.

For example a user could configure categories of "Bathing", "Nail trimming", "Pumping", etc. and would select one of those options for the entry. That would probably make it easier to pivot data for things like display, data viz, and API retrieval.

So if we wanted to just repurpose notes for this we could:

  • Add a title field
  • Add a start time field (distinct from the current timestamp field?)
  • Add an end time field
  • Add the system-wide configurable "category" field

Then it would just be a matter of refactoring the current behaviors to support those fields.

@cdubz cdubz added the enhancement Feature requests or improvements to existing functionality label May 27, 2021
@philip-n
Copy link
Author

Just to go into a little more detail about how my suggestion above would work from a technical PoV.

Data model
One model that stores the actual data (might be called CustomEvent / Note / Entity / ...).
- this model is agnostic about its content and just stores the data that the user inserted -

  • contains the default fields that always apply, just as you described earlier (start, end, note, category)
  • contains some generic fields of different types (boolean, text, number; maybe three fields each?), simply named boolean_1, boolean_2
  • in the db, one such entry gets added each time the user logs such an event

Description model
One model that stores the data description (might be called CustomSchema / CustomFieldNames / ...)
- this model does not store data, but the description of the meaning that the user applies to the fields, i.e. custom field names -

  • contains the "name" of each generic field, and therefore allows to "translate" boolean_1 from the model above to whatever the user named the field
  • if a field is not used, simply store e.g. an empty string or NULL or similar
  • in the db, there is one such entry per CustomSchema that the user creates (system-wide configurable).

At runtime, all values are written / fetched from the CustomEvent-model as usual, but the names for the fields are pulled from the according CustomSchema (purely for displaying).

So in a DB-table view, this would look like:

Description model table

ID category title boolean_1 ... number_1 ... text_1 ...
1 my_medication "Happy pills" "Given with milk" ... "Number of pills" ... ""
2 playground_time "Time at playground" "Played in the sand" ... "Times on the slide" ... "Friends met" ...

Data model table

ID category start_time end_time note boolean_1 ... number_1 ... text_1 ...
1 my_medication 11:03:05 11:04:00 "Took three tries to swallow it" True ... 4 ... ""
2 playground_time 16:08:00 17:43:00 "Went home because of weather" True ... 0 ... "Bonny, Clyde"
3 my_medication 15:017:05 15:18:00 "Was happy taking it" False ... 2 ... ""

Additionally, one could introduce custom enums to allow dropdowns, but first things first :)


I'm not aware of the inner workings of BabyBuddy and or Django, so I don't know if the above would clash with basic principles. From a short glimpse into the Django docs, I guess that there should be no major hurdles (might be different for custom dropdowns?).

The advantages I see are that a) each user can define their things to track, b) there are only generic models at work in the background (no issues with updates / migration), c) the generic / custom-y fields allow to represent and analyze user-defined data (value 2 for pills is parsable, "took two pills" stored as text is not).
Drawbacks: some additional UI-logic necessary, API-routes for custom events do not look nice (boolean_1 etc in the json instead of actual field name).


As I understand your post, my thoughts above are quite similar to what you suggest with the extended notes, plus the generic fields. What you call categories kinda maps to my "description model", and the generic fields are simply a further extension. One might be able to tackle it in smaller steps - extended notes first, generic fields later.

So much for the moment. Does this make sense to you?

@cdubz
Copy link
Member

cdubz commented May 31, 2021

Yep. Makes sense and I am on board. But it’s a pretty big enhancement.

There may be existing tooling for Django that would make this much easier. Here’s a potentially relevant (if outdated) SO discussion: https://stackoverflow.com/questions/7933596/django-dynamic-model-fields

@cdubz cdubz added the help wanted Issues where maintainers could use assistance from others label May 31, 2021
@philip-n
Copy link
Author

philip-n commented Jun 1, 2021

Great! While the SO discussion is a little dated, I guess that the basic principles of the top answer are still valid. My Google-Fu did not turn up many additional interesting results.

Quick summary:

Django-eav sounds technically sound, but abandoned and I'm not clear about the status of the various forks. Also, this seems to attach the same additional fields to all models, if I read it correct (?).

HStoreField is PostgreSQL specific, would require a migration and only supports strings.

JSONField is supported on both PostgreSQL and SQLite, the latter with extension and supports json with native python data types.

MongoDB is not used by BabyBuddy.

django-mutant seems rather abandoned.

Further, there seems to be some implementation in django-payslip to add fields to models, but this is hand-coded and not a ready-for-use tool.

django-user-defined-fields seems to be built on top of JSONField.


The problem I see with all solutions that make use of something json-like, i.e. storing multiple, arbitrary key-value-pairs in one field, is that of consistency. Each record is saved with the latest defined schema, but stored fields are not updated when the schema changes.

Let's say I were to set up my CustomEvent with 3 generic fields a, b, and c. I log some instances, then decide to rename a to d and drop b altogether. I log some more instances, introduce a new field e, ...
--> Now there's x records with slightly different keys.

So currently, I'd vote for a solution as described above, that enforces consistency by always interpreting everything based on the latest description/schema. I fear that this would mean "hand-written" code instead of existing tooling, but would be happy to learn about other options!

@bentekkie
Copy link

I am currently using baby buddy and am feeling the pain of not having this functionality right now.
I am on paternity leave for a while and have some time to do some side projects again.
Would you accept a PR implementing the suggestion above?

@cdubz
Copy link
Member

cdubz commented Oct 25, 2023

Yep! Definitely open to PRs here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests or improvements to existing functionality help wanted Issues where maintainers could use assistance from others
Projects
None yet
Development

No branches or pull requests

3 participants