Skip to content

Instantly share code, notes, and snippets.

@brylie
Created January 5, 2024 23:27
Show Gist options
  • Save brylie/94691b8cb15cd931b4accc3282cd6252 to your computer and use it in GitHub Desktop.
Save brylie/94691b8cb15cd931b4accc3282cd6252 to your computer and use it in GitHub Desktop.
Code with Brylie - e43
(...) Hello and welcome to an open source live code hangout. Today we'll be working on the Jerry Life project.
(...)
I've got a task here.
(...)
We're going to add a modal dialog that will let us add activities to a home.
(...)
We'll run the server.
(...)
We'll load it locally.
(...)
We may use chatdpt to help with certain code conundrums.
(...)
Right now,(...) if I log in,
(...)
I may not have created a superuser.
(...)
Common password.
(...)
Now that I'm logged in, if I open the navigation menu, you will see two buttons up here.
(...)
These allow us to record data that will be visualized in our home's reports,
(...)
such as in these charts.
(...)
We have wellness activities,(...) things that add meaning and fulfillment to life, like going outdoors or listening to music,(...) participating in discussions, or cultural events.
(...)
We also have some metrics to record the types of work that the staff are doing, such as dispensing medication, preparing meals,(...) cleaning, various tasks.
(...)
We want to make sure that the residents in these care homes are receiving high-quality care, that they're living fulfilling lives, and that the caregivers who are employed by the care homes, that it could be institutions or smaller homes, that the employees aren't overwhelmed, and that they're doing work within their specialty,(...) that nurses are doing work that's particular to nurses.
(...)
This is developed in response to some observations in care homes here in Finland, in particular that sometimes the residents weren't leading as fulfilling of lives as they could have. Some residents were more popular than others. There was a disparity in the opportunity to participate in activities. It wasn't intentional. It was more or less accidental because there wasn't a way of making it visible. So we developed this tool to help with that. And then we've also noticed there have been issues in the past few years, in particular with worker dissatisfaction.(...) There have been strikes and a few things
(...)
that helped us recognize that there's an important,
(...)
or the importance of staff doing work that's appropriate
(...)
and not being overburdened.
(...)
On the flip side, there's legislation that says, that kind of guarantees that the residents in these homes get to participate in cultural activities, for example. And we want to make sure that we're living up to that legal requirement as well as the expectation from the family and the residents. So yeah, this is the purpose of this JERELAC tool.
(...)
And of course it can be deployed anywhere. It can be used in any country, but we're particularly modeling it after the Finnish care giving model.
(...)
So in order to move this, to record work, we have a modal dialogue here. And it just lets you pick the home.
(...)
And it's the same thing with the residents, activities, sorry, resident activities.
(...)
There's a form.
(...)
Now the work form appears in a modal dialogue.(...) And you have to select the home, the work type, caregiver role, et cetera.
(...)
And there's a little bit of a bug here.
(...)
We shouldn't be displaying both of these. That could lead to inconsistencies.(...) I think one of these is a drive field. I'll have to fix that.
(...)
Let's just put an issue on here while it's fresh.
(...)
So I'll take a quick screenshot.
(...)
As far as I understand,(...) this tool should record the metrics in one unit, a time unit of minutes or hours. And then we can derive other units,(...) hours, days, weeks, you know, from the initial unit. But we shouldn't collect it in two units. So there's some confusion. I don't know how that got added. I'll have to fix it.
(...)
But basically,(...) so this is the one we want. And I'll annotate it real quick just so it's visible, so it's obvious.
(...)
Annotation, so we have like a rectangle here. That should be good. And if I click the rectangle,(...) and I draw it around this, let's see what happens. Yeah, that's about it.
(...)
Good.(...) Okay.
(...)
Now we'll copy this into a GitHub issue.
(...)
And I've been using chat GPT to help me with creating a GitHub issue.
(...)
So if I just kind of say,(...) oh, and this is interesting too.
(...)
This I should actually add to the project and issue templates so that when I open a new issue, we have it already in place.
(...)
So let's do this. Let's add issue GitHub issue templates.
(...)
Let me just make sure I don't lose my image here. I'll just keep it in the background for a moment.
(...)
Well, feature request template.
(...)
And as far as I recall,(...) we can use form syntax.
(...)
Wow.
(...)
Let's see if GPT knows about the GitHub template syntax. I think we should create a bug report and feature request.
(...)
Nice. So it's got a markdown field saying, you know, thanks. It's got an input.
(...)
Huh.
(...)
Placeholder required field. Wow, this is good stuff.
(...)
Motivation.
(...)
Interesting.
(...)
So we'll go to the GitHub issue template directory, which doesn't yet exist.
(...)
We will create a feature request. A.e.mo.
(...)
We should do the whole thing, I think.
(...)
We'll create a bug report one. The issue is a bit vague. They're all issues. But then if we say features, which are enhancements, bug reports, which are bugs, then we get them already sorted into appropriate buckets.
(...)
And so starting here with markdown, which is I was kind of expecting that because the default is you just pop some markdown into the text area and people will sort of follow it. But it's not always a guarantee. That's why then we use this issue form issue template.
(...)
And I'm not sure if this exists, but if we can do a select menu for the operating system choice.
(...)
And it's not so more relative, but it could be useful just as an experiment to see if it would work.
(...)
And then what we can do is link in our project to the feature request template with a button, the bug report template with a button, and then the discussion template.
(...)
Yeah, it has dropdown support. Wow.
(...)
Yeah, and we could just capture the high level.
(...)
It could be useful to ask in the browser.
(...)
So I'll add that.(...) This is very cool.
(...)
Very comprehensive.
(...)
I don't want these to become too much of a barrier to submitting issues.
(...)
And these aren't always relevant. Some of the bugs could manifest to the lower level of details, but then the web browser.
(...)
In any case, what do we have? What do we have?
(...)
We have a, I'm trying to think alphabetically, but Safari,(...) what we should do with Firefox.
(...)
Chrome,(...) Edge,(...) Chrome, Edge.
(...)
There we go. And other,(...) not applicable. That's a good choice.
(...)
Leave the not applicable part.
(...)
All right, we'll give it a try. This is a good first draft.
(...)
Thanks. Now, how do I think so?
(...)
So, yeah, see if it knows a little bit about the GitHub configuration.
(...)
All right, so we'll commit these.
(...)
It's exciting.
(...)
Yeah, we'll check our contributing. That's a good suggestion. So it's very thorough. It's given me more advice than I asked for, but it's helping me think about details I would have overlooked otherwise.
(...)
So do we even have a contributing? You know, that's a good thing.
(...)
So I'm going to paste in the context windows getting larger, so you can kind of paste in whole documents now.
(...)
You can ask, and I have done this in the past, GPT to role play as different roles like senior software engineer or open source contributor or new contributor and then say as a new contributor, what would you expect to see or what would be helpful for you to for us to include in a contributing guide?
(...)
Okay, so it's saying take the existing document and first just say how do you contribute issues and bug reports and suggestions.(...) That's the easiest way in, like the low,(...) like if you imagine a curve of, you know, gradually getting further into the project where coding is one of the more honestly difficult areas. And we want to encourage people to contribute in many ways beyond coding.(...) So yeah, this is saying this is a helpful onboard on ramp. So welcome all kinds of contributions. So basically reporting bugs feature requests.(...) Honestly, the feature requests are probably more important.
(...)
I think ideas at this point are more important.
(...)
But it's all good. Well, let's move the feature requests.
(...)
Let's see the community discussions is the first place I want to promote that one. So let's bring that up here.
(...)
Then then feature requests, which are excellent.
(...)
This happens to be alphabetized now. Okay, now development.(...) It's a more complicated thing. You got to be familiar with Python, virtual environments, probably Django,(...) HTML, CSS, JavaScript, depending on the type of task you're doing.(...) All right, so let's insert a table of contents code of conduct. We don't have one of those, but.
(...)
Table of contents right there.
(...)
Help people navigate a bit.
(...)
So that was a good suggestion to include details in our contributing guide in our read me. Let me just double check our read me our read me super long now.
(...)
But nonetheless, let's commit this.
(...)
It's not picking it up. There we go.
(...)
Or actually check this out.(...) Magic button.
(...)
Well,(...) pretty good.
(...)
Synchronize those. Now we have a pull request.
(...)
Oops.
(...)
This is your issue templates.
(...)
And so we will need to once I merge this.
(...)
The repository setting, scroll down features, make sure the issue checkbox is there at which it is issued templates.
(...)
Yeah, it says GitHub does not currently support custom buttons for redirecting users to discussions from the issue creation page. Users will need to manually select the discussions to have a certain discussion. I think I've seen evidence to the contrary here, but I haven't. We'll have to double check.
(...)
So it looks like our PR is.
(...)
It's OK. Some style thing there. Let's merge that.
(...)
Yeah, so much. Real quick off stream. Just make sure there's no sensitive stuff. If not, then I'll just show this how GitHub works from people should be fairly.
(...)
Maybe it aren't all familiar. I don't know. So let's see.
(...)
OK, so here it is. We've got the on the settings page. We've got the.
(...)
OK, so here it is. We've got the on the settings page. We've got the.
(...)
Feature request first. But report and let's just take a look at custom blank template for other issue types.
(...)
What did this do? OK.
(...)
Now, if this is going to be like markdown or some kind of text, it looks like it's going to have me open a pull request.
(...)
I believe there will be a way I can add at least like a link to our discussions page on this. Let's see what it says. My proposed changes.
(...)
My create a new branch to start a pull request and see what file it opens. What is it changing to files?
(...)
All right, so we've got.
(...)
No.
(...)
Didn't work. I was hoping.
(...)
Strange. OK, let me see if there's get up docs docs about this.
(...)
It could be that I named him. Yeah, I'm also being more.(...) OK.
(...)
But hey, it's working. It's actually rendering the form.
(...)
Let's see if you have likes this one.
(...)
Our RCI is running again. Go to the settings. Set up templates. We already have them.
(...)
All right, so I have to refer to the documentation.
(...)
You can define different input types, validations and such and such. About issue and pull request templates, configuring the issue templates for your repository.
(...)
Syntax for the issue forms.(...) On GitHub you do main page and you go to settings.
(...)
Use add template menu to preview your thing. Do that.
(...)
You're finished editing preview your template.
(...)
Click on proposed changes.(...) Click my changes. Create issue forms. Currently in beta and subject to change.
(...)
You can create issue templates that have customizable web fields.
(...)
To use an issue form in your repository, you must create a new file and add it to the .github. Here's an example of an issue configuration.
(...)
Here's the rendered version.
(...)
Choose repository where you want to create the issue form.
(...)
In your repository create a file called github-issue-template-formname.
(...)
The body, do your thing, commit.(...) Configuring the template chooser. You can now...
(...)
Yes!(...) Define a config pi.
(...)
You can have links in there. Super cool.
(...)
[Music]
(...)
GitHub...whoops...issue...template. Just make sure I spelled it correctly.
(...)
And we got a couple of the YAML files in there. Here's an example config file.
(...)
It'll customize the template chooser when the file is merged into the repository's default branch.
(...)
It's almost good enough, but the confusing part is how do I specify an issue template for one of these links? Hmm...
(...)
[Music]
(...)
[Music]
(...)
Adding config YAML under GitHub issue template is a great way to guide the contributors to the correct resources for their specific needs, such as feature requests, bug reports, and community discussions. The config YAML file you're planning to add will help direct contributors to the appropriate channels.
(...)
Ah, so you have some metadata here. Templates...bug report YAML. Hey, there we go.
(...)
[Music]
(...)
So...config.yaml.
(...)
[Music]
(...)
All right, so...
(...)
[Music]
(...)
Hopefully we don't have to specify the feature. The labels are already part of the template. Just feature_request.yaml.
(...)
All that should be part of this template. I mean, it is.
(...)
[Music]
(...)
Bug reports...
(...)
template.bugreport.yaml.
(...)
And then our community link.
(...)
And fix the URLs still.
(...)
Maybe we'll start...
(...)
with the community link.
(...)
And I think I need this whole thing.
(...)
Looks good. Now this is subject to change.
(...)
I need to stage those changes.
(...)
I'm going to commit it to the main branch and just push that up there. Not a best practice.
(...)
But I just don't want to open another pull request for that one.
(...)
Okay, so now we have...
(...)
an issue template configuration. I guess...
(...)
if I go to new issue...
(...)
[Music]
(...)
Somehow it... Okay, so it automatically picked those up.
(...)
And it kind of merged the two.
(...)
Well, that's okay. So I guess if I just delete these configurations here and leave the community support one... hopefully that'll be...
(...)
that'll work its way out. And these are fine. Get started.
(...)
I am plus these open a new tab looking thing.(...) It's kind of awkward.
(...)
Okay.(...) Well, it's progress. That's what it is.
(...)
[Music]
(...)
I like it. So now it helps me...
(...)
have some structure in my future requests and error reports.
(...)
And helps new contributors to know what kind of information we need.
(...)
When we're submitting a bug report or feature request.
(...)
And one thing I'm curious... Yeah, it gives us the rich text field. Very good. Okay, I'm going to take a quick break.(...) We'll come back. This was a bit of an aside. I'll create the... I guess it was a bug report.(...) Yeah, for the form, the modal dialog. And then we'll continue with the task at hand of creating a different modal dialog for recording activities.(...) I'll be right back.
(...)
[Music]
(...)
Okay, good to go. So that was actually kind of fun and interesting. Learning more about open source and how these platforms work.
(...)
So now we're going to create a bug.
(...)
This is strange.
(...)
Title fields a bit redundant.
(...)
Let's fix that. Just takes a moment.
(...)
And let me check the feature request. It's probably the same problem. It's got a default title, but then okay.
(...)
It just doesn't need the additional title.
(...)
[Music](...) Can we put the bug emoji?
(...)
That's the one.
(...)
[Music] Is emoji the plural of emoji?
(...)
[Music]
(...)
Okay, I'm out of ectoplasm today.
(...)
I've got my orange power.
(...)
Issue, new issue.
(...)
And I believe this is a bug report. [Music]
(...)
[Music]
(...)
Work. What was it?
(...)
Oh, I had the annotation wrong. Dang it.
(...)
[Music]
(...)
Duration minutes, duration hours.
(...)
Login.
(...)
[Music]
(...)
[Music]
(...)
These can be optional, I guess. The default if not applicable.
(...)
Let's see how it looks.
(...)
Now, I wish it would not populate the fields where there was no response, but okay.
(...)
No response is sort of like not applicable.
(...)
All right, but there it goes. Nonetheless, we've created a bug report template and an initial bug reports.
(...)
On to the task at hand.
(...)
45 minutes later.
(...)
Let's make sure I've got everything here.
(...)
We will create a new branch.
(...)
I believe the modal is the right solution.
(...)
And there's a couple of opportunities here. The minimum viable is to wrap this form in a modal dialog.
(...)
What the residents feel, I guess this is, yeah, they would be filtered to the home level.
(...)
There's potentially a lot of residents.
(...)
One improvement for this form would be to group the residents by home.
(...)
So these should all be residencies.
(...)
And then we would have a grouping.
(...)
It's a bit complicated, but that's more useful, I think,(...) to the end user.
(...)
So I have done some research on this.
(...)
Let me take a look real quick at some shoelace components.
(...)
Web components. I'm trying to keep this project very simple.
(...)
Maintainable forward thinking in terms of longevity.
(...)
Which might mean not adopting all of the most exciting technologies that are going around right now in the JavaScript space in particular. Because that'll lead us to a more brittle project that'll sort of disintegrate every couple of months.
(...)
It feels like.
(...)
So I'm not using any heavy front-end framework.
(...)
And I'm trying to invest in web standards because that's created with longevity in mind.
(...)
The shoelace framework is one of the few true web component frameworks that I'm aware of.
(...)
Now what I'm looking for here, do they have a form component for choosing?
(...)
If not, that's cool.
(...)
I mean, this is pretty nice, and it selects multis. So put multis, like perhaps.
(...)
OK, so they call it option.
(...)
Perhaps the option supports multiselect.
(...)
OK, so DL select.
(...)
Grouping and multiselect is what I'm after.
(...)
Placeholders, clearable. It's nice. Pill. So multiple.
(...)
This is looking good. Grouping.
(...)
They have option groups. Yes. Yes. So this, I believe, is a fairly sustainable move to the application of the
(...)
Web Standards-compliant component framework.
(...)
Which is one of the reasons we use Bootstrap.
(...)
It uses SAS for defining and compiling the styles, but it's basically just CSS. So it's a very simple way to use it. So you can use it for the application of the web. And then you can use it for the application of the web. But it's basically just CSS.
(...)
We just want very simple projects, simple aesthetics and semantics.
(...)
And a project for these components, such as Bootstrap, that's been around for a while.
(...)
And is under continual improvement.
(...)
Now, one problem with shoelace style I've seen in the past is I believe it suffers from the single developer syndrome.
(...)
Which is kind of one strike against projects when I'm evaluating them.
(...)
You can see here it's just primarily Core-Levisca.(...) Fairly prolific.(...) But also the contributing graph is a bit tapering.
(...)
Granted,(...) it's a web-standard component library, so the code will, I believe, age well.
(...)
We'll give it a try.
(...)
And the first thing I'll do is just try to improve this form.
(...)
Which may be sufficient for the minimum viable.
(...)
I would like to install it from a CDN, so that I don't have to introduce any build tool.
(...)
So we'll go to the main website.
(...)
I'm just very minimal with this project. I'm very hesitant to add complex build tooling to touch much in the JavaScript ecosystem.(...) I like the language, and I like the fact that JavaScript is a web-standard. But the ecosystem, I believe, is just a very simple project. I like the language,(...) and I like the fact that JavaScript is a web-standard.(...) But the ecosystem, I believe, is just really dysfunctional. I've lost trust.
(...)
So it has a light and a dark theme.(...) We're going to have a toggle between light and dark.
(...)
So I should take that into account.
(...)
So let's actually create a different branch.
(...)
And I'm not going to create an issue for this, but we'll create a branch to enhance the add activity form.
(...)
Now we're not supporting light and dark theme toggling yet.
(...)
So actually, this is good to keep in mind, but I'll use the default dark theme. I'll copy this code into our main template.
(...)
Core? No, common templates.(...) I don't even know anything in here, I think.
(...)
I should delete that.
(...)
Okay, so in this project we have them here. So base HTML.
(...)
We'll load the style sheet. And I script at the bottom.
(...)
One problem we're going to encounter is this is auto-generated. All right, so we've got the basic dependency loaded in.
(...)
We'll go to the activities, templates, the form here.
(...)
I might make an argument later that lets us pass in the resident options or something like that.
(...)
But for now, we're just going to reconstruct this.
(...)
And make sure it's localized.
(...)
So for this,(...) I'm going to ask chatgbt for a little bit of help to prompt my memory.
(...)
(eerie music) I have a little bit of duplication here,
(...)
but essentially...
(...)
(eerie music)
(...)
(eerie music)
(...)
See if it gets some help if it zeroes straight into the...
(...)
template code or if it's gonna encourage me to do it in Python, form helper.(...) (eerie music)
(...)
(eerie music)
(...)
That could be good right here just to add the class.
(...)
(eerie music)
(...)
(eerie music) (eerie music)
(...)
Yeah, so it's proposing a few ways. (eerie music)
(...)
(eerie music)
(...)
Now I need to put the class directly on the form field.
(...)
(eerie music)
(...)
(eerie music) So...
(...)
(keyboard clicking)
(...)
(eerie music) We'll manually render the template, that's what I was thinking.
(...)
(eerie music)
(...)
Now we've got two forms that are roughly doing this,(...) duplicated one another.
(...)
I think this is the one I should be maintaining.
(...)
(eerie music) I can tell by the fact that it uses a save button.
(...)
(eerie music)
(...)
And then it's called resident activity form, which is a bit different. So this is just a remnant that I had forgotten to delete.
(...)
(keyboard clicking) All right, so let's see if we can just...
(...)
(eerie music) I don't remember if I mentioned...
(...)
Oh yeah. (eerie music)(...) A bit about the markup and the translation in particular. (eerie music)
(...)
So we'll see how close this gets us.
(...)
(eerie music) (keyboard clicking) (eerie music)
(...)
If I can just refresh.
(...)
All right.
(...)
So that works. So this is also one problem I've had with the...
(...)
(eerie music)
(...)
Shoelace templates, they just do weird things in the doc.
(...)
With the shoelace components.
(...)
Let me just first see if this works
(...)
with the other fields.
(...)
Okay, so that's one problem.
(...)
(eerie music)
(...)
(eerie music) (eerie music)
(...)
(keyboard clicking)
(...)
It's like it almost works.
(...)
(eerie music) I'm wondering if the CSS is not loading here.
(...)
(eerie music)
(...)
(keyboard clicking) And since it is, I don't know why this has got a transparent background.
(...)
(eerie music) (eerie music)
(...)
(eerie music) Because of that.
(...)
(eerie music)
(...)
(keyboard clicking) (eerie music)
(...)
(eerie music) Yep, all right, well this won't work. This is the second time I've tried it.
(...)
In a different project I tried it before and got some just weirdness.
(...)
Just like this, it's...
(...)
Just...
(...)
I don't know how to describe it. It's just kind of...(...) It doesn't work correctly.
(...)
Let me make sure I've installed it, installed it correctly.
(...)
(eerie music)
(...)
(eerie music) (chuckles) And maybe I should include it at the top of my...
(...)
Base template.(...) It doesn't sound like a good idea.
(...)
Nope, still the same problem. What if I include it up top?
(...)
Then we wouldn't have that flash of unstyled content.
(...)
Now it says I can include it after though, after the CSS.
(...)
But I don't have any other scripts here and even Bootstrap is like,
(...)
fairly chill without anything, any scripts up top here. Still have that flash of unstyled content.
(...)
While the thing loads, shoot.
(...)
Alright, back to the drawing board. So again,(...) I'm gonna try using...
(...)
CDN to install shoelace. I don't want to install it with a build tool. (eerie music) It rendered it.
(...)
It was just buggy.
(...)
Okay, so there's the form back.
(...)
(eerie music)
(...)
Maybe...
(...)
Maybe I'm not using the correct select semantics because it's a multi-select.
(...)
But that's how it looks.
(...)
(eerie music)
(...)
Alright, so the nervousest thing I'll select too. (eerie music) Which has jQuery dependency.
(...)
Is there a select three?
(...)
(eerie music) Looking for a library similar to select two, but without jQuery.(...) I mean, I'm not opposed to jQuery. I just don't want to add unnecessary dependencies. So, granted I just went ahead and added a big shoelace thing, but I thought we were gonna get some components out of it.
(...)
And jQuery would give us some things as well, but most of those,(...) I believe we can pretty much do with...
(...)
You should have a nice select. With regular JavaScript. Okay, wait, first thing, okay, two years ago, so that's already done.
(...)
Let's try...
(...)
Select multiple.
(...)
Choices, vanilla JS. I knew there had to be something.
(...)
Two years ago, two years ago.(...) Well, it's vanilla JS.
(...)
Uh...
(...)
(eerie music) (sniffling) (eerie music) (sniffling) (eerie music)
(...)
Let's see what else.
(...)
Five months ago,(...) modern looking select field for form,
(...)
submits which can be customized.(...) There's not any jQuery. I don't know why we need bootstrapped, but okay. It's the license.
(...)
(sniffling) Oh, I see.
(...)
What does it look like?
(...)
Lemon squeezy.(...) (eerie music)
(...)
You have to do it one at a time, though. Nice single select.
(...)
With group tag.
(...)
It's a bit much, it's a bit much. I don't think we're gonna go with something like that.
(...)
Alright.
(...)
A lot of stars.
(...)
(eerie music)
(...)
I don't want to install view or react to get just a select widget.
(...)
(eerie music)
(...)
November 20th. Twenty-two and two.
(...)
(sniffling) (eerie music)
(...)
Agnostic.(...) Autocomplete widget with native, I guess autocomplete is what we're out of keyboard feeling. Just JavaScript.
(...)
(eerie music)
(...)
Check the insights,(...) contributors.
(...)
Now it's a widget, so I don't have high expectations. If it was like a framework, like web development framework, Django, for example.(...) Yes, I would want multiple contributors. So it looks like this project's had a handover from one contributor or one maintainer to another one.
(...)
And then a lot of kind of one-time contributors, which is cool and it's common.
(...)
(sniffling) (eerie music)
(...)
So we have a group.
(...)
If I hold shift, I can select multiple.
(...)
Without holding shift, I'm able to select multiple.(...) We can remove.
(...)
Looks good.
(...)
It's installable by a CDN. Lightweight, 16 kilobytes. Let's then a common JPEG image.
(...)
(sniffling) And it just uses a select UI control, which is one of the problems web components face.
(...)
You can't override or it's difficult to override the default browser widgets, like form controls and buttons. So I don't know that the web APIs with web components were, I don't think they included that ability. So you can define custom components and new components with a shadow DOM and all that stuff. But really, just styling the default ones, I think was still left as prohibitively difficult.
(...)
But here we go. So it's got an ID.
(...)
And then the style sheet after that. And this is okay. But all right. And then you have basically, Tom selected.
(...)
(sniffling) (eerie music) (clicking) (eerie music) (clicking) (eerie music)
(...)
(clicking) (eerie music) (clicking) (eerie music) (chuckling) (eerie music) I think that's gonna be probably the best bet for now.
(...)
(eerie music) (clicking) (sniffling) (eerie music) (clicking) (eerie music) (eerie music)
(...)
(eerie music) And then one thing I'd like to do.
(...)
(eerie music) (clicking) (eerie music) (clicking) (eerie music) (clicking) (eerie music) (clicking) (eerie music) It's grouped in by home. So you have a bunch of select options, but inside of groups,
(...)
(sniffling) define the choices with groups. Firstly, define your choices in a way that they are grouped.(...) Each group has a tuple.
(...)
Where the first element is the name of the group, and the second element is a list of tuples representing the choices in that group. So kind of key value.
(...)
(clicking) (sniffling) (sniffling) (eerie music) (clicking) (eerie music) (clicking) Excuse me. So this is cool.
(...)
(eerie music) (clicking) (eerie music) We could start with just that. (eerie music)
(...)
In our view,
(...)
there's an activity list view,
(...)
there's an activity form view.
(...)
(eerie music) (eerie music) (eerie music) (eerie music) (eerie music) (sniffling) (eerie music) (eerie music)
(...)
Now I would need to pass the resident list into the form view.(...) So there may be like a get form context or something like this. I don't have that great of knowledge into the Django framework internals, but a lot of that knowledge is latent within the QPT-4 because the Django's very well documented, also very widely used. So there's a lot of training material.
(...)
(eerie music) (clicking) (eerie music) (eerie music) (eerie music) (eerie music) (eerie music) So there's, if I can get inside of a function where I have access to the database, I can generate the group list. I just want to know that I can connect the dots and where do I generate the list. Probably like a get context,(...) get form context, get form data.
(...)
Modify your form to accept the resident choices as an argument. Ah.
(...)
(eerie music) So there's a long...
(...)
(eerie music) Okay, alright.
(...)
(eerie music) When you initialize it, you just grab... (eerie music) Huh, choices.
(...)
(eerie music) (sniffling) (eerie music) (sniffling) Ah, alright.
(...)
(eerie music) (eerie music) (eerie music)
(...)
Then override the form. So basically I'll read this a lot. It's like,(...) step one, modify your form to accept resident choices as an argument. First modify your resident activity form to accept resident choices as an initialization argument.(...) And this modification, resident choice is an optional keyword, quarg, keyword argument that's not provided. It'll default to an empty list. (sniffling) Alright.(...) So we're going to get the value out of the quargs.
(...)
Ah, cool, I can reply to specific.
(...)
Lines.
(...)
Alright, then...
(...)
(eerie music) When we're setting up the get quargs,
(...)
(eerie music) we will generate this list. Okay, there we go, there we go.
(...)
Resident choices.(...) Very cool, so what we'll do then...
(...)
(eerie music) Is a little bit of debugging, but we'll copy this in...
(...)
(eerie music) In a moment. (sniffling)
(...)
I'm just going to get into the context.
(...)
(eerie music) Get form quargs.
(...)
Override the get form quargs and methodize the residents to the form.(...) (eerie music) Interesting, okay, now here's the deal though.
(...)
(eerie music)
(...)
I'm going to have... actually, if GPT in the form of Co-Pilot can help us out.
(...)
(eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music)
(...)
And just...(...) (eerie music)
(...)
Feeding in more context.
(...)
(eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music) Now the key is that...
(...)
(eerie music) (eerie music)
(...)
(eerie music)
(...)
We have a residency object that links residents to homes.
(...)
So, we first need to fetch...
(...)
(eerie music) (eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music) Alright,(...) so with this context in mind, let's see what we can get. Resident choices, starts with an empty list. Homes, residency object filter, move out is null, values list, home name, flat is true, distinct homes.(...) Okay,(...) then we're gonna, I guess, iterate over...
(...)
(eerie music)
(...)
Those homes and get the residencies for them.
(...)
(eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music)
(...)
Yeah, it seems a bit redundant that I'm...(...) (eerie music) (eerie music)
(...)
I'm querying this multiple times, and this is gonna create a lot of queries.(...) (eerie music) You know, rather than a single unified query.
(...)
(eerie music)
(...)
So let's give it a little more information about the residency model.
(...)
(eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music)
(...)
(eerie music) (eerie music) (eerie music) As few queries as is possible.
(...)
(eerie music)
(...)
(eerie music) (eerie music) (eerie music) (eerie music)
(...)
So this is an aggregation,(...) and here we are with our models. We have residents who are linked to homes by residency relationship.
(...)
(eerie music)(...) So if I just provide this model here,(...) that should be sufficient. (eerie music)
(...)
Let's see if it picks up on the fact that full name is a property method. It's not actually stored in the database, and we want the full name.
(...)
To optimize the query for retrieving residency objects grouped by home and then accessing home name and resident full name. So did catch that it was a method.(...) Assuming full name is a method, the resident model.
(...)
You should utilize Django's database optimization tools like select related and prefetch related. Yes, okay, very cool.
(...)
These tools help in reducing the number of database queries by fetching related objects in advance.
(...)
Step one is optimize the query. So we got, we're going to write a function too, which is good for my testing standpoint.
(...)
So we're going to get the resident choices by filtering the resident C objects where the move out is null.
(...)
And we will select a related home and resident,(...) so we have those fields available. So that's a single database query and it will fetch everybody,(...) including the homes.
(...)
Then we are going to iterate over those, but we won't have to do a database query for each one. So this is looking good.
(...)
And I believe this can be a private method for the time being.
(...)
So we'll define it up here before the view.
(...)
It's basically an aggregation.
(...)
Then our get form quarks is very clear.
(...)
I don't know how to do all the heavy work.
(...)
At that level of abstraction, we've encapsulated it.
(...)
Because we're just focusing on the quarks, I don't need to know about the structure of the collections and prefetch related and all that stuff.
(...)
All right, so now we have a method, a function to use, and I believe the init should come first and it'll get called in whatever order.
(...)
All right, let's see.
(...)
I'm wondering.
(...)
If I would just.
(...)
So we don't need to do any popping or if it's just more direct, right? Yes, you can certainly call it your resident choices function directly in the init method of your resident activities. This approach simplifies the process and avoids the need to use get form quarks and pop any arguments.
(...)
So you can just get rid of that.
(...)
That.
(...)
And the initializer here is a bit better as well. It's like the copilot is using almost chat gbt three five. I'm not sure what the version is, but you know, there's some definitely qualitative differences.
(...)
Let's just see what happens.
(...)
Type object must not.
(...)
All right, maybe I spoke too soon. Let me double check.
(...)
Or if I just say super init.
(...)
String is not callable.
(...)
Nine twenty four.
(...)
Maybe because it's treating as a property.
(...)
So.
(...)
All right.
(...)
So the self refers to.
(...)
You.
(...)
Oh, that's why I'm in the wrong place. Okay. All right. I have to add this to the form. Makes sense. I'm adding to the view. My bad. I'll take a quick break and be right back.
(...)
You.
(...)
Excellent.(...) All right. So we'll move our helper function.
(...)
And the initialization to the form.
(...)
Cool.(...) Which was.
(...)
The metrics.
(...)
App.
(...)
Forms.
(...)
You might put an order by there.
(...)
Let's just get this into the UI.
(...)
Cool.(...) Residency is not defined.
(...)
So no longer.
(...)
Querying by residents explicitly. We are querying by residency. There we go. Home no home zero home one. Very good.
(...)
And I can't select the home of course just the residence.
(...)
Yeah,(...) so it works. I mean the default browser multi-select which is needs a lot to be desired.
(...)
At least I could change the height of it. But yeah, it's not very great user experience. We're making progress though.
(...)
One thing is the.
(...)
Yeah, the residents aren't alphabetical.
(...)
Oh.
(...)
That might be a bit trickier.
(...)
Might be asking too much but we should really should be alphabetized by home and residency services.
(...)
Wow.
(...)
That works great.
(...)
Alphabetize.(...) Just as way.
(...)
To alphabetize you have a dictionary sort. Okay.
(...)
Resident choices list by both home name and the resident name you can sort the dictionary entries.
(...)
Okay, we can sort the top level which is to sorted.
(...)
And they're not named tuples so we have to use the index there. All right. That works though.
(...)
But unfortunate because of the relational nature of our data it's difficult to sort these.
(...)
string is not callable
(...)
yeah so it's property the full name property it was still a bit confused by the fact that I told it was a method earlier is just doing what I had told earlier and it works very cool that's already a really big improvement wow I
(...)
really can't ask for much more this has already been a big help but I'm going to try we're gonna make this is easy for people as possible and it can be helpful if we have like a multi-select widget that even lets you type a few letters filter the name that you're looking for I believe this one even had type head type type type yeah see and it shows the title so this is good for 16k select i's JS with four main objectives modernizing the code base decoupling from jQuery expanding functionality and addressing issue backlogs and get on board with that so usage
(...)
it's got a style sheet in the script I'm gonna just put them together in the base template this is gonna get me back to the question of how to add the class but I believe you just do that that's pretty cool with the ID though that's kind of strange no no no no it's this yeah you just gonna find the element so I can find the element by name or whatever it is using a CSS selector here this is gonna work I think template so our base HTML let's check our indentation here
(...)
I'll try to actually just would like to try loading this at the bottom to the first script loading and you can use the defer keyword even to make it better so we're allowing our JavaScript to run first I wonder if I put defer here that's how you do it well I'm not gonna worry about that until we look at our lighthouse score but essentially now on the the form page
(...)
I need to add a little bit of extra JS so we can come down here activity template that one
(...)
I'm gonna delete block extra JS and we have to wrap it in the script tag our extra JS doesn't include that and I have to get the DOM element by rendering the page which it already is and I can just inspect it which it is name is residence ID equals ID residents I think so CSS selector ID residents hash hashtag and let's try it all right so let's do a console log just to see hello there hello nurse I'm not really like waiting for document to be ready or any of that stuff Tom's like is not defined okay well actually I just realized I should only really be including it where it's used essentially likewise we have this extra CSS block for this purpose put that here
(...)
and in here paste that now first we'll check hello was working oh and it worked nice really good now one last one last thing dark mode support I'm not super set on dark mode I like to provide it and especially when I'm working on the code I like to have a dark screen because it's like a big flashlight right here in my face I've already got lights and there's enough light coming at me right now so no dark mode
(...)
all right no worries
(...)
so TS wrapper
(...)
and TS drop down
(...)
so what I'll do is create some custom styles hopefully I don't have to do important that works I don't have to do important though I'm loading in the correct order important shouldn't be required yeah now the actual color I want essentially matches I think it should basically match this this is good I can't really get that color without an eyedropper more tools settings
(...)
oh it's just a gear
(...)
throw me my drops color bigger basically after a quarter the elements tab under styles click on any color preview box huh you have to go all the way in there just to give it a color picker all right
(...)
well this one's pretty close so what's that
(...)
all right so we're pretty close opt group header interesting some slightly dark gray that's cool co-pilot figured that out it didn't quite work
(...)
all right so I have to say TS drop-down I have to be more specific basically it's looking for specificity and mine wasn't specific enough so the more specific rule takes the game takes the cake TS drop-down space now we have matching specificity but I have the cascade I guess it's this is the right word it's the one that comes out I come next it's not just like cascading into words but like it's loaded the previous styles and then now it applies my rules so it's the ordering I have the last word and it's just as specific as the other words that have been spoken man have to arrange so many of these option active so again TS drop-down I'll organize
(...)
so then it knows that this should match wow it's crazy there crazy there there we go okay getting close so it's essentially TS here I'll just try applying a background color
(...)
so we will want that
(...)
and B
(...)
Yeah, this is cool. Maybe I'll indent it just slightly.
(...)
Wait, yeah, last thing.
(...)
TS Hexalia.
(...)
To get into this.umbling.
(...)
Didn't get it, almost.
(...)
So TS control,(...) item input.
(...)
No, that's the next thing. This is the item.
(...)
Specificity again.
(...)
TS wrapper.
(...)
TS control.
(...)
Oh, I'm trying.
(...)
Okay.
(...)
Okay.
(...)
[Music]
(...)
Man, CSS is incredibly complex in all these rules. Yeah.(...) Didn't need to be calculated. But hey, it looks good.
(...)
Wow.
(...)
Made it.
(...)
[Music]
(...)
It stands out a bit.
(...)
One thing is this, I don't know how much I want to fiddle with it, but the outline here.(...) So I can remove that. Where's the outline coming from? [Music]
(...)
Not the TS wrapper,(...) but probably the TS control border none.
(...)
[Music] So here we can just say TS control border none.
(...)
[Music]
(...)
And essentially I'd like it to resemble this.
(...)
[Music]
(...)
So I think I'll invert the colors.(...) Because we sort of need to indicate multiple selections, I think, right?(...) Or at least get them an outline.
(...)
Could be that.
(...)
But what if I do...
(...)
[Music]
(...)
No.
(...)
I have to refresh.
(...)
[Music]
(...)
How did I do that?
(...)
[Music]
(...)
Why can't I select this?
(...)
It's like the browser.
(...)
I'm all not going to fight it. I don't care that much.
(...)
[Music]
(...)
Strange. Why is this element the last active?
(...)
What's the point of making it active also? Is it so I can remove it?
(...)
[Music] A lot of subtlety here.
(...)
Hmm.
(...)
All right. Let me see if this is documented. Tom, select.
(...)
[Music]
(...)
See if that worked.
(...)
Just a bit of an aside, but that's pretty cool.
(...)
No, it didn't work.
(...)
[Music]
(...)
It did work. It was on the wrong side.
(...)
[Music] Hmm.
(...)
So the zero and eight picks, does it max even work with that? Should work with that.
(...)
[Music]
(...)
Okay.(...) Yes, there's FEP integers.
(...)
[Music]
(...)
I can fix that. I'll open a pull request for that.
(...)
Holy mackerel. What did I just copy?
(...)
Just this one, right?
(...)
Oh, it didn't work.
(...)
Oh man.
(...)
[Music]
(...)
Clear button. [Music]
(...)
I might have to use important here.(...) [Music]
(...)
Hmm. Maybe I'm wrong. [Music] I don't want to fiddle with this too much.
(...)
But that should just be enabled by default to clear. Like select two, it just was enabled by default.
(...)
Hmm.
(...)
[Music]
(...)
Okay, remove button. Will that work?(...) Yeah, that's...
(...)
How about remove button?
(...)
[Music](...) Yes.
(...)
Looks better. Okay. Can't clear it. Full able, at least we can remove them.
(...)
[Music]
(...)
Good progress.
(...)
[Music] So we have a multi-select form. Does it work? Does it work? Let's create a record on the fourth. Yeah. For those residents,(...) they had a guided loop activity for 30 minutes.(...) And there was a hobby instructor that stopped by and led a yoga workshop. Something like that. Saving it.
(...)
30.
(...)
And what it does is creates a record for each of the residents.
(...)
They should have a corresponding activity ID that... or group activity ID that shows it was a group activity and that these were participating in that. But in any way, we split it out into individual activity records. And Mary G.
(...)
I don't know what home they're at.
(...)
Nicholas L.
(...)
Was it Nicholas L? I don't remember dang names.
(...)
Mary G and Alexander W. They had activities today. So there it goes. It worked.
(...)
I'm going to take a quick peek at what the other plugins are doing.
(...)
I don't want to get too deep into it.
(...)
Carrot position.
(...)
Okay.
(...)
Checkbox options. Well, hey, that's kind of cool.
(...)
Maybe it's a little easier to use.
(...)
Although I should say it was fairly easy to use as it was.(...) There we go. Let's take a look.
(...)
Add activity.(...) And that should be refreshed. Now we have checkboxes.
(...)
Yeah, maybe it's just more explicit that way. That you can select the residents but not the homes.
(...)
Okay, I can deal with that. Nice improvement.
(...)
Noise one. Clear button didn't work. I'm not sure why. I'm not going to debug it.(...) Drag and drop.(...) Interesting. Interesting. Drop down header. What's this?
(...)
All right. Then you select residents. Hey, that can be kind of cool.
(...)
So then I would add a dictionary entry for
(...)
this one.
(...)
To use as a mixed dictionary approach.
(...)
No, it broke. It broke. It broke.
(...)
So I guess if I want to configure like that.
(...)
The whole plugins thing a lot of people dictionary.
(...)
That won't work.(...) But let's just pull those up for a minute. Then basically actually all I need to do is
(...)
test this out. Well first.
(...)
Interesting that it knows about those.
(...)
Granted I'm guessing or using hallucinations of the large language model.
(...)
But that worked.
(...)
And now I can localize it. Cool.
(...)
Since we're in a temple I can.
(...)
Let's see.
(...)
The template just do that.
(...)
Maybe if I use an empty dictionary it's just.
(...)
Come on.
(...)
All right. So you have to have an option in there.
(...)
So it's working a moment ago.
(...)
That won't work.(...) Because those are not dictionaries.
(...)
This should work.(...) That works.
(...)
Let's see if it's a matter of translating.
(...)
One step at a time. OK so that's what doesn't work.
(...)
This is why it doesn't work because it's trying to use JavaScript but we're actually technically in a Django template.
(...)
Don't need that.
(...)
All right so we just go back to that.
(...)
We're working with the remove button in the checkbox options and I won't worry about the headings and translations right now.
(...)
It's hard to get a title basically.
(...)
All right.(...) What does this do.
(...)
No.
(...)
They can actually search.
(...)
Nice.
(...)
No nothing like that.
(...)
That was weird when you had to know active items. What's the point of that.
(...)
I don't know there's something that you can do active actions you can do on active items.
(...)
All right that's a little bit better.
(...)
So I'm glad that's a configuration variable.
(...)
I wonder if it's obvious though without this dropdown input that you can actually.
(...)
The comments are different.
(...)
You can search here so this is kind of interesting.
(...)
I like this better than the dropdown input.
(...)
Backspace delete. So this is interesting. I hit that.
(...)
Then you can delete.
(...)
I think since we have the delete button maybe we can disable the backspace delete.
(...)
I don't know.
(...)
I'll try to make it accessible so people can navigate with a keyboard.
(...)
That's interesting.
(...)
I don't think I want to use that.
(...)
Oh cool.
(...)
So if we want to query them from the server that's Andy.
(...)
Plug in.
(...)
Okay I think we're finally good to go.
(...)
And really the change is fairly minimal. Just took some tweaking and trial and error and styling but overall it's pretty good.
(...)
Let me just take one quick look at these and see if I can organize them a little bit better.(...) So at least alphabetical might help me.
(...)
Rapper and specificity. Rapper is like multiple.
(...)
T is dropdown so I'll move those up.
(...)
I like it. Glad there's an option out there. It seems like it's pretty nice actually.
(...)
I'm not like, we're not supposed for choice in here. If I were using React or something like that, I know there's some really great overview. There's some really great component libraries for those front-end libraries.
(...)
But yeah, it seems to take on... Unfortunately, you have to go all in on a front-end template rendering system just to use some components.
(...)
Maybe there's a way to use them without these component libraries,(...) without a view. But like, let's see. I don't want to go too much further into this, but...(...) Vanilla JS libraries,(...) Riot JS,(...) Pure JS, JavaScript template engine.
(...)
Yeah, I didn't really do any search for a whole UI framework.
(...)
They have some plain JavaScript stuff, "Symbol and elegant component-based UI library." Version 9?(...) Hmm.
(...)
Front-end is crowded. Riot JS offers the right balance. Here's where we need custom elements.
(...)
Human readable.(...) Yeah.
(...)
I like XML.
(...)
HTML.
(...)
Close to standard. That's what I'm talking about.
(...)
But the components like API.(...) No polyfills. No proprietary event system. React. XML root elements. That was what got shoelace, I think. That's pretty cool. I think that's maybe why shoelace was breaking.
(...)
Create them with Rust, even. Any preprocessor. But do I need to use a preprocessor?
(...)
Wow. And they're comparing it with these other...(...) This is not apples to apples, right? It's a component library. These are like... I would have had to even call them sometimes a framework, but these are reactive data binding or DOM manipulation libraries.
(...)
Maybe that's what it means. You still have to define them. Okay, so it's not like a component library. It's a UI library. That's what they're saying. Literally. If I were to define my own... But I would like a component library.
(...)
Okay, about to have a get away from this.
(...)
I'll give it one more shot.
(...)
Demo, kitchen sink.
(...)
Now I can already tell.
(...)
I don't want to create them. I just wanted some off the shelf.
(...)
Component libraries built with those.
(...)
This is a search for another day.
(...)
So strange.
(...)
It's...
(...)
I don't need a reactive data binding thing.
(...)
So maybe I'm using the wrong terminology, but a component library in my mind is like a library of user interface components.
(...)
Basically like web components that are already made. Things like buttons, modal dialogues, select widgets.
(...)
Carbon design is what I was considering.
(...)
We did give it a shot. We gave it a shot to clarity design.
(...)
VMware,(...) fast design,(...) fast team.
(...)
Nord Health.(...) That would put us more in alignment with Nordic Healthcare.
(...)
CSS doodle. Okay, skipping that. W3 design.
(...)
Two...
(...)
I don't know. It's like trying to be affiliated with W3C, but I don't see how that would be. Mozilla Protocol.
(...)
Reshworks. Design system.
(...)
Volkswagen.
(...)
Design system.
(...)
Modular user interfaces.
(...)
Check it out. Okay, thanks York.
(...)
You.
(...)
But this again is just a...
(...)
I think for another day.
(...)
What's wrong after? Vanilla components. And that's cool that it supports other frameworks. People are, you know, using those frameworks out of them. I'm not trying to be disdainful or, you know, they have different needs than our project, for example. A lot of projects would have more complex UI needs and so Reactor Review could be a good fit.
(...)
I would prefer not to have to use YARN or NPM to install the component library.
(...)
Also, this looks kind of just...
(...)
Like they don't have a good attention to detail. Stuff like this looks weird.
(...)
So this is pretty elegant looking.
(...)
NPM install or unpackage it.(...) Show me the components.
(...)
Accessibility bug. Accessibility bug. And this is kind of why I don't want to invent our own UI component framework.
(...)
There's really complex and important details that need to be worked out. And why I believe it's also important to just use the web standards. Because a lot of those details are baked into the browser for years now. And improving all the time. But if you reinvent the DOM or your own rendering pseudo language like a JSX type of thing. You have to also reinvent all these accessibility things. Now I say that, but I'm also interested in using Flutter. Which is basically... They're rendering everything. So they're doing the same thing in the mobile where they're rendering per pixel. So all the accessibility and everything needs to be baked back into Flutter.
(...)
This is interesting. They have some patterns built in. So yeah, this will be a cool research task.
(...)
Hey, what's up?(...) Yeah. Yeah.
(...)
Izzy, how are you doing? I'm experimenting a little bit with the interface. So I can have the chat on one side, the community, and then...
(...)
Some other metadata about the stream.
(...)
Thanks.
(...)
Hey, what are you up to today? How are you doing? I know you're doing good. I'm a bit tired. It's been a long day. But just kind of checking out some of these design systems that are... That support Vanilla JS projects.
(...)
This one's the one most compelling if they mean by Nordic. This is interesting.
(...)
Nord Health.
(...)
Built products that refine healthcare. And we're... Because we're a health-oriented project as well. And the Nordics...
(...)
So let's see about us.
(...)
We're in Nordic roots. So our project is based in Finland. So there's an affinity there.
(...)
Very cool. They got components.
(...)
Yeah, very cool.
(...)
A lot of components actually.
(...)
They're select. Let's see. I just spent a bunch of time on this multi-select widget.
(...)
We have less than six options. So there's maybe a multi-select or a larger component. They should offer some advice.
(...)
This...
(...)
Let's see.
(...)
There we go.
(...)
You got censored by the bot. So your messages came in the wrong order.
(...)
Yeah, it's fine. Yeah, it happens.
(...)
Yeah, I built this project.
(...)
JLF Caregiving.
(...)
And it's mainly just using HTML and CSS and JavaScript to power the charts.
(...)
And as we grow,(...) we're either going to go heavily into HTML and web components. It is bootstrap.
(...)
I'm just using something that's kind of mature and stable, not going to fly away.
(...)
That has more than one core maintainer, for example. It has been around for a while and continues to adapt and evolve.
(...)
And supports good accessibility practices. Things like that, out of the box.
(...)
Bootstrap checks a lot of the boxes for me.
(...)
We're using the latest Bootstrap, Bootstrap 5. I also don't like utility classes.(...) I don't like my HTML to be so messy. And I know that people say, "Just try Tailwind and you'll change your mind."
(...)
But I think HTML and CSS kind of were designed with different purposes in mind, different ends in mind.
(...)
HTML is like a semantic layer that describes a structure. And CSS is a declarative layer that describes aesthetics.
(...)
And just like I don't... I try not to mix CSS in those things. Or HTML and JavaScript or Python, basically. I think those language boundaries exist for a reason.
(...)
But yeah, you're right, Bootstrap looks like Bootstrap is one of the things.
(...)
So today we just added this widget that lets you have a multi-select. And I did a little research. I was trying to find a vanilla JS multi-select. And it's kind of challenging to find one that's maintained. It doesn't have a lot of dependencies, you know, so a small footprint. A lot of them come with jQuery. And I'm not opposed to jQuery. I just want to keep a really small footprint. So every dependency I'm trying to kind of vet.
(...)
So we ended up doing this TomSelect.
(...)
Yeah, this is surprisingly challenging.
(...)
Oh, it's actually right here. So if you want to check it out. And you know, it's relatively recent maintenance.
(...)
Yeah, and again, I'm not really against jQuery. I think it serves a lot of projects really well and it's still in wide use. And I think it's also continuing, under continued development, has a lot of contributors.
(...)
But as much as we can, we're just trying to keep things real slim. So when I look at an open source project, I look for recent commits. I look for multiple contributors, which this one didn't quite meet.
(...)
Concurrent contributors with significant contributions. So this one has, it looks like a handover of maintainers. And then a bunch of contributors who made small improvements,(...) but nothing, you know, like that's sustaining it.
(...)
But I decided that since it is under recent development, it is vanilla JS. It is relatively small, doesn't have any dependencies.
(...)
And it's just for one single form widget.
(...)
This select widget also can be installed via CDN, so it doesn't require a build tool. That was another thing I don't want to introduce, NPM or something like that, just to get my widgets to work.
(...)
I checked out a bunch of boxes, and so I just give them the lack of other options that went with this one.
(...)
But as a quick aside, I was just checking out if there's more holistic vanilla JS component library that we might incorporate in.
(...)
Similar to how we're using a charting library that has a lot of types of charts, because there's a lot of complexity when you start to build UI components, including things like accessibility.(...) So I want to stick close to the web standards, close to the DOM,(...) and build on the backs of people who are very talented.
(...)
Yeah.
(...)
Yeah, that's true.
(...)
They had apparently the predecessor selectize.
(...)
JS was a fork from selectize.js. Okay.(...) Decoupling from jQuery.
(...)
And then Tom Select somehow continued that fork of a fork.
(...)
Probably focusing more on using maybe modern JavaScript features. I haven't quite looked into it, but it has some nice plugins.
(...)
What did you end up getting? We used select two on our previous project. It was really great, but it has a jQuery dependency.
(...)
And then there was this Quasar framework we were using with the view.js, but I'm not using any reactive template rendering.
(...)
Binding utility like view or react.
(...)
So I don't want to add a component library with a dependency on view or react just to get a select widget in particular.
(...)
We were looking at this Quasar at one point because we want to make this very mobile friendly and potentially publish this in app stores. But right now I'm just for this as we are in the prototype phase. I'm just targeting HTML in the web browser.
(...)
Yeah, that's a good compromise. Select two is super good.
(...)
And this is what I searched for earlier. Select two without jQuery. And apparently other people are doing that too.(...) Select two is super nice.
(...)
It's very mature and let's check out the commit history.
(...)
Two months ago, relatively recent.
(...)
Seems like it's had a long history and a lot of commits, so it's taken a while to churn the numbers. Here we go. Okay, but yeah, this is assigned to it's kind of tapering off. The development is coming to a halt in a way. It could be just in maintenance mode. They don't need a lot of improvements, but that's also a sign that the projects help might not be good. The original developers gone and handed over ownership.(...) So this two months ago commit was probably like a CI thing or a bump from somebody.
(...)
Doesn't say much, but I can check the history.(...) But yeah, jQuery. How big is that?
(...)
Yeah, eventually I'll probably have to get jQuery in here, won't I?(...) But I'm curious what I would use it for.
(...)
Because I'm also as a Django developer looking closely and following the development of HTML.(...) I think that would solve a lot of any dynamic UI needs I would need and avoid DOM manipulation because I would really be going to have to make an Ajax call and then render a bunch of DOM elements with JavaScript. I would just do that on the server, make an HTTP request. Oh man, yeah, right. I've really been avoiding React. I don't know what it is. I think I just don't like everything being in JavaScript. It gets messy and it leaves developers way too much room to hang ourselves basically by mixing things and defining styles and DOM in any arbitrary order. You know, it throws away a lot of existing tooling. It makes the build process slow and cumbersome and adds complexity to development and lifecycle.(...) I don't like mixing though.(...) HTML and CSS in JavaScript, I think that's really a big mistake. So I've looked at Vue because it at least attempts to separate out the concerns and I believe the concerns are separated on the language boundary because the languages are designed for specific purposes. I mentioned earlier that HTML is a hierarchical semantic layer and CSS is a declarative aesthetic layer and JavaScript is an imperative.
(...)
Logic layer and those really shouldn't blend too much. They're different mindsets.
(...)
Next from Vue. Yeah, I've taken a look. That looks interesting. What do you think of Svelte? I haven't used that. I haven't really had a need for it. Now I'm at my day job. I'm like a backend engineer so I don't know. I just work in Python and you know, JSON and GRPC.
(...)
I don't have to worry about too much frontend stuff. We have really talented frontend developers.
(...)
So yeah, I can't think of really a use case where we would need a jQuery type of thing.
(...)
And I might end up adopting like a vanilla JS component library if we need more advanced user interface components.
(...)
I'm thinking about probably this Nord Health design system. This is really nice looking.
(...)
They have screen reader support and stuff. This is really important stuff.(...) Wow.(...) Yeah. And this is sort of like where our app is headed, to be honest.
(...)
Yeah. Do you have any open source Django work you've been able to contribute to? Wow,(...) this is cool. This is inspiring me.(...) I should really take a look at this. Imagine this home profile page right here as a really nice.(...) Hopefully they support dark mode. But yeah, each home you could select that and manage it as like a dashboard with widgets in the sidebar menu. Wow, this is good. Export the data.
(...)
Yeah,(...) it's not a big deal, of course, but something I've really been interested in for many years and have been orienting myself towards that. And so I just don't want to be curious. And I like to look at other projects on the stream as well. So not a big deal. I'm not trying to be judgmental or anything. I'm just curious.
(...)
And it's, you know, I'm pretty lucky to have the opportunity to do some open source work as well. It's something that's inspiring to me.(...) Yes, I wonder if this Nord Health supports dark mode. I'm not super fixated on having, yes.
(...)
But it's really nice, especially when I'm working. If it supports out of the box and we can toggle our themes.(...) Man, this was a good find.
(...)
Okay,(...) but are you able to at least find some time in your primary work to do Django oriented stuff?
(...)
Yeah, this is basically you install from a CDN as far as I understand getting started.
(...)
And it's got supportive tools like a Figma toolkit for the designers as well.(...) So you can override the things with your own branding, then it's not so bootstrap, which was the first thing you saw this would take us away from that bootstrap aesthetic into a more modern design system.
(...)
I don't know if this helps if I paste the link in the chat should actually you can click everything.(...) I know it's really unfortunate that I think I don't know. It's like even people are confused what a web framework means like a web development framework. And what we're losing when we move away or throw away projects like Django,(...) Ruby on Rails, Laravel are also mentionable. I haven't worked with Ruby much, Rails much, I mean, or Laravel, but I think they're in the same vein where it's like a actual web framework where you have a lot of things that are not available.
(...)
Surprisingly complicated. And a lot of times you don't even know you need them until you do some, you know, things like password hashing, or like, how do you store securely passwords and things like that.
(...)
So I think authorization authentication are things you have to kind of cobble together. If you just do like a node JS system, even using something like backbone or whatever.
(...)
I've been looking in the JavaScript ecosystem for something that's batteries included on this gale of a Django or Ruby on Rails, there's a few that have kind of emerged in tapered sales.
(...)
JS, feather JS.
(...)
We used Meteor JS and it turned out to be we bet on the wrong horse there.
(...)
They at least have authentication.(...) But I think, you know, if you want to get an ORM and authorization and well I like Django templating.
(...)
Django doesn't come with REST support, so to speak, out of the box. It kind of does, you can serialize JSON, but you have to kind of go to a plugin for that.
(...)
AuthZ, AuthN, okay. [Music]
(...)
Haven't heard of those.
(...)
[Music] Where does your user data live then?
(...)
[Music] Yeah,(...) authentication authorization, okay.
(...)
[Music] So is this like actually a cloud flare service? [Music]
(...)
Okay, and it adds multi-factor authentication.
(...)
Biomoleature.
(...)
[Music]
(...)
Oh, okay. Yeah, Cognito, Mongo Atlas, AuthN. Okay, so we're basically baking in some kind of third party authorization service.
(...)
[Music]
(...)
I remember looking at AWS Cognito, and there was this Python AWS thing that's, oh, I can't even remember what it was called, but...
(...)
[Music] I don't know, it's baked into Django. I don't, if possible, I think we don't really need to hand over our user credentials to a third party service and we can avoid that.(...) But I don't know. What do you think of all Auth?
(...)
Oh, yeah, I see what you're saying. Yeah, with React you don't have, because in the ecosystem, there's not a framework that's all inclusive that has those built in, so you'd have to basically commoditize all of your components. And that's the kind of movement in the web development industry I'm not really excited about, especially like serverless and things like that, where you start getting really fine grained, essentially billing your build at the functional invocation.
(...)
And your function invocations don't share memory and things like that, so you have to basically spawn a new memory allocation with every serverless invocation, and you just get pummeled with fees as you start paying for ingress and egress and all these things that with like a service like DigitalOcean,
(...)
App Platform or whatever, they sort of come with it, and you don't have to really worry about paying that granularly at least.
(...)
So I think, I don't know, I'm a bit skeptical about AWS and I think the industry has been a bit duped by the push for serverless and the commoditization of
(...)
things that basically could just be built into a framework like authorization authentication.
(...)
It's kind of unfortunate and companies pay big for it,(...) like massive, massive amounts.
(...)
And especially like startups who are already sort of strapped for cash and trying to survive for various reasons, but a lot of it is mismanagement of money. You know, mismanaging money on AWS cost is like really a big killer.
(...)
Yeah, for sure. I was at, just for scale, previous work they were spending at the peak, they were spending 70,000 a month. When I was there, I don't know, it's possibly changed since then, but they were in peak startup mode where they had a lot of venture capital money to burn through essentially and cost wasn't such a factor.
(...)
And also it's hard to see your costs on a granular level with AWS at that point.
(...)
Hopefully that's improved, but you can see the cost at the end, the total amount, and sometimes a little bit on a service level, but not if you have a bunch of services. But the moral of that story was we were misusing step functions and step functions were really super expensive.
(...)
And really it could have just been a virtual machine that did a thing over and over and had some state in it instead of step functions. And we were spending probably 30 to 50K on step functions, but then a bunch of other like services, of course.
(...)
Okay, CloudFlare. So is it CloudFlare functions or what's the biggest cost factor would you say there?
(...)
You know, there's things like managed DB and whatnot. I think, you know, those are really helpful.
(...)
I like the platform as a service idea because I don't really want to think at that level of infrastructure.(...) I'm already kind of up to my ears with, you know, Django and writing the application logic and making sure the user interface is good.
(...)
CDN. Okay, crazy. CDN costs so much. Is it like mostly media then like large videos or wow?
(...)
Is it a high volume site? Was it just a lot of image and interesting?
(...)
There is one more JavaScript framework that I was that I keep hearing about. But anyway, that's a whole another aside. I just don't think I have looked I don't think one exists in the JavaScript ecosystem.(...) Frankly, I don't know that a lot of JavaScript engineers know really what they're missing,(...) especially, you know,
(...)
people without backgrounds in Robion rails or Laravel or Django, for example, you just kind of really don't know the scope of it.
(...)
I don't really know the scope of Django, but I'm continually surprised at what it has and how it's just saving me time.
(...)
Just little details that are already worked out, like everything from like handling dates, formatting them in the templates. Just surprising, you know, the middleware is a really nice thing. There was an AWS framework that didn't really support middleware.
(...)
Chalice.(...) This is the one.(...) I was looking at this one because it seemed kind of interesting. It's a micro framework for AWS serverless micro framework because the company I was working at was like super all in on AWS really.
(...)
I was really excited about serverless. If I wanted to justify any Python, anything, it had to be SPA and serverless. Now it's just like so disappointed at a lot of things in the company. But yeah, for example, this chalice, you know, their middleware was an afterthought. I don't think that that's been added yet.
(...)
And this chalice is also just going to put you right into the all the AWS ecosystem.
(...)
They got middleware eventually. Very cool.
(...)
Very cool.
(...)
It's not long after I opened the feature request because I was looking into that.
(...)
Yeah, the developer experience. We haven't even mentioned it. It's like pretty painful. Even at my regular job where we're not in a business. Even at my regular job where we're not in serverless environment board and micro services environment. So when we can't really run our code locally and you know, test and debug things. So sometimes it's sometimes we can we can write a unit test and run that.
(...)
But if it calls any of the external services, for example, or yeah, we can't really run this the whole project locally like I can with a Django project.
(...)
Because it has external dependencies. It can't really start up because of even things like our logging and integrations with like
(...)
service monitoring platforms and stuff like that. So the thing won't even run really locally and debugging sometimes is like I have to commit, you know, working in memory like working like one of my colleagues put it. Interestingly,(...) they said that's like programming by camera phrase, but by imagination, basically,
(...)
you have to like simulate the thing in your head, you have to imagine it. You call it a camera was a better phrase for it. Commit those changes. You know, we have that tool for like pedantic helping and then push it to GitHub. Wait for the CI to run the unit test in an environment that has all the bits.(...) Hey, thanks, AJ, CJ, thanks for the subscribe. And then if the test runs,
(...)
you know, then I can get some feedback like, okay, test failed. This is what happened to somebody expected. I can't even like in Django, I love just being able to put a breakpoint and see what's going on right there. And getting the output of tests in my local environment, it makes a huge difference. Step by step, I'm able to iterate and see things and don't have to simulate so much of my brain,
(...)
which, you know, our brains aren't super good at that. That's why we have computers doing it. Yeah, it's like, I think it's, but I think it's not just Python, the language is the, I believe it's the ecosystem, also the ethos of the developer community.
(...)
We value these types of things. And when I was doing JavaScript, primarily, I wasn't really aware that I needed that.(...) And maybe, you know, I'm generalizing here, but I think it's just not the same ethos, at least, in JavaScript community. And there's, there's also a lot of sort of like a tendency to want to be the next person at the conference talk showing why you're revolutionary or revolutionizing the front end and why now hooks are the next thing you need to learn or whatever, whatever incremental innovation it is. I don't see so much of that kind of evangelism in the Python ecosystem. I'd say it's perfect, but there's more of like an ethos of like building things to last and building on other things like extending pandas and built, you know, like the data science ecosystem is largely working with pandas, data frames and stuff like that.
(...)
Django seems to be keeping pace. It's moving towards being asynchronous fully asynchronous. There's been significant progress there.(...) I was a little bit disappointed how channels shook out how I don't think there's a guarantee that all your subscribers will get the data that they're subscribed to.
(...)
By design decision.
(...)
Hey, what's up rebel welcome.
(...)
Okay, cool.(...) Man, well, I might as well just start up another
(...)
task.(...) I could actually do this modal dialogue.
(...)
That was what I initially set out to do. So let me publish the branch and merge this and then we'll look at making this modal dialogue reusable to where I can pass in the data for the resident selector.
(...)
We can have the global add activity page, but I think it's also convenient. If you can just pass it in at the home level and just select from the home residents.
(...)
So let's continue here.
(...)
It's 9pm. What the heck, let's go for it.
(...)
It's also cool when there's actually people hanging out to chat. It's motivating.
(...)
So wait for that to run.
(...)
So what I'm going to do is actually create a reminder to myself to take a closer look at this Nord health or create an issue with the new issue template. We just created at the beginning.
(...)
Maybe a discussion for that one.
(...)
Oh, I don't know.
(...)
Nord what they call it. Nord health design.
(...)
Because this, as you mentioned, CJ will have the benefit of making our app look much more presentable professional,(...) particularly in healthcare systems where we're basically trying to appeal towards
(...)
professionals in group home or institutional care group care 24 seven assisted living and we don't want to be.
(...)
You know, to looking like Microsoft Excel or something like that, but we should have a professional aesthetic and bootstrap is clean and clear, but maybe we can add a little bit better polish there.
(...)
So let's turn to GPT.
(...)
I think I was in here when I did the Jeep.
(...)
What else?
(...)
Just by the color.(...) Crazy. The dark theme.(...) Oh, that's almost the same as the GitHub users. I don't think that they use. It's this kind of. Yeah. Off gray. Be g dark. Nice.
(...)
Let's see. Well,(...) that's probably enough information for tragedy to help me write just a basic. Reminder to check out this Nord health design system.
(...)
Or implemented. That's a good.
(...)
Yeah, the interesting thing is I'm trying to we have a feature request open to build a toggle between the background dark and back on light so people have a choice.
(...)
I defaulted it right now to dark so I could work on it without straining my eyes. That also means we would need to toggle these charts, which is just a similar flag in the plot. The library to say.
(...)
Dark theme, light theme, but we'd have to coordinate it. And since we're not using a client side reactive library or something like that, we have to make it full page refresh, which is fine.
(...)
That's by decision.
(...)
So we would basically need to persist it in the database, which there's a pull request open that adds a collection for user preferences, including the medic toggle and language choice. So we are working on performing supporting multiple languages.
(...)
We don't have it. We don't support it yet. Is that what you're asking? Is that what you're asking?
(...)
Well, the thing is.
(...)
Yeah, it depends how you implement it.
(...)
But I'm really relying on server side rendering and these chart libraries.
(...)
Render on the server.
(...)
And I don't think.
(...)
I don't think there's just a.
(...)
Class that I could swap out on the charts.
(...)
So it's got to be coordinated. Yeah, it's I don't mind. Quick reload. I think browsers have gotten a lot better about not flashing white and not leaving the user staring at a blank page and reloading, which is the. Whole thing at spawn the SPA.
(...)
Initiative.
(...)
Yeah, we're using a plotly pie, so our metrics are pretty much. Python functions.
(...)
Which are defined charts. Right here, for example, we prepare some data. And then we get a string, which is actually just HTML.
(...)
And essentially is plotly pie. Just take some configuration.
(...)
And it takes the data as a data frame or a list of dictionaries.
(...)
And we can configure it after the fact and the. Dark mode toggle somewhere.
(...)
Maybe I'm missing it.
(...)
Anyway,(...) that's yeah.
(...)
Polly is pretty good, though. It's pretty much sure documentation leaves a little bit to be desired. And then we can do a little bit of a demo. And then we can do a little bit of a demo. And then we can do a little bit of a demo. And then we can do a little bit of a demo. Just start. Sorry. It doesn't leave this.
(...)
Be desired.
(...)
But I mean it works really grief. This is actually one I was trying to get a horizontal bar chart with plotly just a single row.
(...)
And it had too much chart junk. I couldn't get it slimmed. You don't get this one with HTML.
(...)
But these are the ones this type of stuff is incredibly complicated and I wouldn't want to bake my own plot lasts.
(...)
consideration about what we should use for the long run.
(...)
And I'm evaluating Plotly against
(...)
a couple other ones like E-charts.
(...)
I'd like to write mainly Python though.(...) It's not a hard requirement. I don't mind a little bit of JavaScript for the charts, but it's nice if Python can generate the JavaScript for the charts and I can just think in Python the whole time. But E-charts is very nice. I hope you checked this one out.
(...)
It's now an Apache project.(...) But then there's great ones in the Python ecosystem like Seaborn,(...) but we want our plots to be interactive. So then we would look at bokeh,
(...)
which does pair interactive charts rendered
(...)
or prepared on the server and then rendered in the DOM.(...) But it does the JavaScript for you.
(...)
So this is what I'm considering. But making a switch from a plotly to another library is a pretty big undertaking. So at this point in the project, it doesn't really make sense.
(...)
We'll merge that.
(...)
There was another interesting one. You just use the grammar of graphics.
(...)
Can't remember the name of it,(...) but it also produces interactive plots.
(...)
(soft music) Plot nine, haven't heard of that one.
(...)
(soft music) Maybe it isn't the grammar of graphics. We haven't misspoke, but there's a Python. (soft music)
(...)
(keyboard keys clicking) (soft music)
(...)
Oh.
(...)
(soft music)
(...)
Where was it in Oregon? Altair, there it is, found it.
(...)
Yeah,(...) Washington, E.D.(...) So this is an interesting one as well.
(...)
So these would be my main candidates for an alternative to Plali.
(...)
You know, it's gotta be comprehensive and handle things that are very complicated and well beyond my capabilities.
(...)
And there's statistical nature because our plots could potentially start becoming more analytical.
(...)
But also give me a nice ergonomics, ergonomics. So I just wanna be able to pass in a data frame and say these are the columns, these are the type of values, and this is the type of chart.
(...)
Yeah, let me know what you think about those. See what you come up with.
(...)
But yeah, here's an example. You get your chart, you get your data,
(...)
you define a chart, you pass the data in the tabular form. So I'm assuming this is a data frame,(...) pandas probably.(...) So I pass the data and I say, hey, here's my X and Y.(...) You know, I don't have to, a lot of the charting libraries, like even Plali initially, you have to kind of map over your data and split out the columns into essentially,
(...)
you know, one dimensional list or whatever.
(...)
But I don't wanna even have to think about that. I just wanna say, I'm gonna be more declarative(...) when we talk about colors and the plot type and stuff like that. So yeah, and then we need it to be interactive.
(...)
Because what we're trying to do is help people give them a framework that they can
(...)
start asking their own questions. We can't anticipate what all questions people wanna ask.
(...)
Another interesting thing is cross filtering, if we can do that. But right now we don't have any charts that would be good for a cross filtering dashboard. But you know, you select a date range in one chart and all the other ones are updated.
(...)
Some really good examples of that like,
(...)
Datadog has really good dashboard support and I'm thinking there's a few other,(...) you know, Plali has the framework.
(...)
Dash.
(...)
And I believe with Bokeh, you can also do similar,
(...)
you have similar capabilities, but with Dash you kind of quickly get(...) into their enterprise mode. You get sucked into that. That's one of the reasons I'm a little bit skeptical about Plali.
(...)
Okay, but let's get to some interesting stuff.(...) I mean, it's all interesting. I'm having a good time talking about it. So let's create this issue.
(...)
(piano music)
(...)
(piano music)
(...)
Okay, cool. Vacation brain. Yeah, I'm like on permanent vacation brain.
(...)
(laughs)
(...)
As I get older, my brain is just more mushy.
(...)
Very cool. The tragedy of fatigue has been really helpful(...) in a lot of ways.
(...)
Like writing all this for me, you know, kind of expanding on my ideas, help me kind of flesh out things and think from different angles that I wouldn't otherwise.
(...)
It's pretty good. I'm just gonna take it wholesale. I'm not gonna read through it. It's kind of a copy and paste issue.
(...)
25. Hey, you're in your peak. No need.
(...)
Yeah, yeah, that's good.
(...)
Now look at that. It's a good issue.
(...)
I will add a help wanted and I don't know if it's a good first issue.
(...)
Probably not. It's a bit complicated, but yeah, it could be something just a proof of concept that might be easy for someone.(...) Well, happy 25 though, by the way. That's really cool. What did you do to celebrate?
(...)
This is literally the peak here, biological peak that is.
(...)
And you survived the most,
(...)
pretty much the most dangerous period of our lives is around the ages of 18 to 25. When we're most error prone, we're doing brazen and, you know, thoughtless.
(...)
Actions, the biggest mistakes in our lives, we usually make them in that range, that age range. So wow.
(...)
Life is hazardous of course, but yeah, surviving to 25 is a big achievement.
(...)
Hey, but then there's your family. That is the most important thing.(...) That's like everything in fact,
(...)
is what I'm kind of reminding myself of.
(...)
So yeah,(...) everything is extra.
(...)
(soft music)
(...)
All right, let's see. So we've got a nice issue there and emerged my thingamabob. So let's look at some beautiful bootstrap modal dialogues.
(...)
Now I can close all these cause we've got, oh that's super nice, that's dark mode.
(...)
Hell yeah, I was going to take a quick look at this. Grammar graphics. Okay, so yeah, it's not super much the point, grammar graphics wasn't the point, but the declarative interface to graphics was the point. All right, cool. So I will now pull down the changes from main
(...)
and hopefully this will be fairly straightforward. It's essentially when you're viewing a home,(...) make sure the server's running, you go to a home here
(...)
and instead of using this add activity that is sort of the global,(...) you know, maybe the nice,
(...)
maybe it's unnecessary though,
(...)
but maybe you just want to add an activity for that given home,(...) selecting only the residence for that home.
(...)
Could be confusing to users to have a global activity, add activity on the navigation menu and then having one down here on the home.
(...)
Let me see what else it does.
(...)
(soft music) Well,
(...)
this is one.
(...)
Yeah, so in a way the COVID kind of helped,
(...)
helped increase your odds of just survival and not doing something that you'll regret.
(...)
Until you're 80.
(...)
(laughs)
(...)
So this is one where we're starting to get into access control. We're using default, the built-in Django(...) authentication framework. And now I need to add essentially row level permissions(...) on the home level. So each home should have authorized users.
(...)
First I just need to be able to add them.
(...)
Then when I'm doing things like listing homes, we'll only list the homes that a user is a member of, stuff like that. And if they try to visit a home they're not a member of, they'll get an authorization error,(...) not authorized.
(...)
This is really important in institutional care where you need to control access
(...)
and preserve privacy and things like that. Okay, well let's give it a try. Let's try this one out.
(...)
Now,
(...)
we have the Django admin. So that's where we'll probably start then.
(...)
Get it working in the admin first.
(...)
Starting at the model level.
(...)
So for this, it's interesting.
(...)
What would be a good name,(...) home users? (soft music)
(...)
Let's see what chat GPT says if it can give us some options.
(...)
(keyboard clicking)
(...)
(keyboard clicking)
(...)
I'll also read this aloud in a second.
(...)
(keyboard clicking)
(...)
(keyboard clicking)
(...)
So it's essentially defining a Django model class that will be used for access control by connecting user accounts to home model instances. For example, when listing homes on the homes page, the page lists only certain homes that the user is a member of. We'll also likely need to attach some metadata to the intermediate table,
(...)
such as can administer or some other semantic like that, or is admin, I don't know.
(...)
Something equivalent to there will be some users who can manage the home. They'll have additional privileges
(...)
and some who can only access the data and maybe perform basic activities like recording an activity.
(...)
So let's just see what GPT says when I just kind of express what I'm trying to achieve.
(...)
The one thing I would like to ask it for is what are some good class names for this? But sometimes if I just tell it what I'm trying to do,
(...)
I'll get much more than I would have even thought to ask.
(...)
Okay, and even generating some code. So to implement an access control mechanism in Django where the user accounts are connected to home model instances with varying permission levels, such as can administer,(...) this is GPT for really good stuff. You should create a many to many relationship between the user and the home model using a through model here.
(...)
This through model will hold the metadata for the relationship, such as permission levels, yes. Here's an example of how you might define your models.(...) So you have the home, user home relation,
(...)
unique together user home, so there should only be one user home, yep, relation per user home,(...) and then home.
(...)
Members, okay. Many to many fields through user home relation, and then we can, wow, define the model, metadata there.
(...)
Super good.
(...)
Yeah, and I don't mind being explicit that it's a relation.
(...)
Yeah, so that's pretty good.
(...)
Now,(...) well, it knows that I need to inherit from, get the auth model user, but we actually have a custom user model. So I'll just change it up there, there's no problem.
(...)
So essentially,
(...)
really good, show me how to get populated in views,
(...)
and how to administer it.
(...)
(soft music) If you need to attach more metadata in the future, you can simply add more fields to the home user, user home relation,(...) home user relation, (soft music) to flexible access control.
(...)
(keyboard clicking)
(...)
So I'm wondering if there's any ideas for model methods that we could use that would sort of let me encapsulate the authentication logic,
(...)
that way it would be attached to the home, for example, and I could take a request user and pass it into can administer or something like that. That way I don't have to define that in the views, which potentially could sprawl across multiple views.
(...)
But yeah, so home is a member, that's a good one. Home can administer, so that's good. And that way you have this idea in Django, fat models, the model has a lot of responsibility,(...) and your business logic mostly resides in the model,(...) and a little bit in the views, but not very much in the template, we don't mix too much logic there, right?(...) So this is cool, I think this is a good design. So let's take a look at this. I'll call it home user relation, since we're gonna put this in the home models,
(...)
and primarily the perspective here is coming from the home, the home is where the authentication logic lives, stuff like that, so yeah, just a small change in perspective of the nomenclature here of the model.
(...)
Okay, so we got our home defined here, (soft music)
(...)
here,(...) and we're gonna apply a similar thing to the home group, but it's gonna get complicated, but essentially,(...) we can have people who are working in these institutional care facilities and networks that could be quite large, in fact, this tool was originally built in the city in Finland, and we deployed it across the whole city at the later stage of the project, the trial, we had like a,(...) originally we were prototyping it, and then we had a longer term project, it lasted about three years, and we got a lot of feedback and made a lot of improvements, it was great opportunity, and we're hoping to reboot the project this year, we're a bit dormant, business, our business is a bit dormant, but the open source project, I'm rebooting it now,
(...)
in preparation of Hopeful 2024.
(...)
Okay, so where is this? Home is quite large, we've got a lot of properties, and a lot of these are relating to analytics and stuff, but here, I wanna add just a home group, or what I was getting at though is, we'll not only need access control at an individual home level, but there's clusters of homes, like a campus,
(...)
that where you originally built this project, just in this care home that was in the campus, it was something like a thousand residents, and we started in just one of the homes there, and then we knew that we needed to group the homes together, and have access control, some people couldn't see the whole system, some people only see one home, so that's why we have this home group, and we'll add further access control there.
(...)
I just need a general pattern.
(...)
And I need to get the,
(...)
well, it already knows it's a user's user, so I guess that's good,
(...)
but I can import this helper, Django helper, to get the user.
(...)
We co-pilot knows.
(...)
It's core utils get user model, isn't it?)
(...)
There it is. I know it's hard to use this one, but it's still a lot better than the other one. I don't always remember that stuff and sometimes it's quicker now to get the large language model to sort of suss that out for you by prompting it rather than kind of going to Django docs or StackOverflow or something like that. I found it more effective just to work my prompting skills a bit.(...) So here we actually just want to grab the user model.
(...)
Pretty much remember and there's a lot of embedded information latent in the machine learning model.
(...)
Generative AI.
(...)
Yeah, so this is going to return from our settings. It's going to look in our apps for our settings auth user model which I've defined in our settings. So it's right here. So it knows where it is and it'll grab it. Good. Next up, let's see what the copilot suggests. Okay, it knows I'm going to go for the home.
(...)
Home's home.
(...)
Now since we're in home models, I think we can just do that. I don't know.(...) Six and one half dozen and another.
(...)
Cascade related name home user relations.
(...)
So we've got from a user we have home user relations and from a home we have home user relations.(...) It should be fine.
(...)
Now let's see.
(...)
I do two is class meta.
(...)
Seeing how much the GPT and the copilot differ. Okay, I like to, I like this. I like defining my database tables and the meta. But it didn't know about the unique together. Didn't consider that. Let's see if it gets it here. Constraint. Ah, so it's adding a constraint this way.
(...)
Interesting. Well,(...) this is if I type unique together user home. It's a bit more straightforward that way.
(...)
Let's just see if it comes up with anything else. So we got the stir method.
(...)
So let's maybe put that in there. Self user, self home. Yeah, good.
(...)
Get absolute URL. We don't really need that. No, we don't need that. But it's good. This is I kind of like let the LLM kind of explore the space of common.
(...)
Possibilities and a lot of times I come up with some interesting stuff. So maybe we'll just define this stur method before the meta. I don't know. Classmen. I don't know what sequence to define these, but okay.
(...)
So very close.(...) And then.
(...)
Is this many too many feel necessary? I suppose if I want to use members.
(...)
Ah, but this I believe is going to get me user objects.
(...)
Yeah.
(...)
So this is some Django magic as far as I understand.
(...)
Because if I just say home dot home user relations, I'll get home user relations. And since this is an optical one extra degree to get to the user optical home user relations for each get the user. I think that's the difference here. So let me add this members field here. This is a fat model. I might have gone a little bit too far in my fat model design with Django.
(...)
But I can clean that up. No problem.
(...)
Yeah.(...) So the same thing here.
(...)
But since I'm using it in a couple places.
(...)
I'm going to use the same reference user model.
(...)
After all my imports.
(...)
Something like that. All right. All right. All right. So we've got migrated changes. It's looking good, though.
(...)
Conversely, if I add a home's property, yeah, on the user I can say homes get the homes. Remember,(...) one problem is I need to group these into into groups. It's going to get complicated.
(...)
Make those migration.(...) Okay.
(...)
Laser reference to user information but app homes doesn't provide a model user home relation.
(...)
Okay.
(...)
It's a bit challenging here. Okay.
(...)
Let's see. So it's ordering is defining user home relation before the home and then it can say through.
(...)
And then the problem is this is weird. So this is the hallucination home is we're going to define it here or here but not both places. That's weird. So it's hallucination. I need to just.
(...)
Use string reference and maybe they'll help.
(...)
So we make migrations there. All right. Well, it's a bit of a mind boggler. That's no problem.
(...)
We'll see if GPT can help us out a little bit.
(...)
Here your encountering is likely due to the order of definition of your models and how Django results model references in main to me field through a custom through model. Here's how you can resolve this. Ensure the home user relation model is defined before it's referenced. Okay. That was what I was kind of thinking.
(...)
But then do we have to make sure that the home is defined before the home user reference.
(...)
This is a bit tricky situation.
(...)
Yes. It's assuming both home and home user relation models are in the app name homes.
(...)
Well.
(...)
I don't need this helper.
(...)
I don't need this members helper because I will have the reverse and I can get the members I can make a property.
(...)
I'll show that in a minute. Let's just get these migrations to work and then we'll make a property that essentially is going to grab the home members and from a user to grab the homes. They're a member of hopefully with home groups. But let's see. Will this migrations work?(...) Should.
(...)
Yes.
(...)
I'll migrate that in. So then if I register with the admin we should be able to start working with it for a moment.
(...)
Yeah.
(...)
So we'll run that server.
(...)
This looks good. Then we'll commit these changes and we will then work on the.
(...)
I think I'll just add the property well here working with this stuff. So now we have home groups home user relations and home.
(...)
I guess it's not what the ties is then.
(...)
But essentially I can select a user and a home.
(...)
Saving that. That was it. Shows me that but if I try to add myself again.
(...)
To home to.
(...)
Or exists.
(...)
Good. That way we don't get polluted.
(...)
Authorization.
(...)
Instances. OK cool. So this user is not technically authorized to do anything. I said that I'm a user super user and we just haven't built any authorization logic.
(...)
But that's progress. We're making progress.(...) So just while it's fresh on my mind I will add the property method to.
(...)
Members is what I'm after.(...) Residence.
(...)
Self query set user model. There we go. Returns a creation of all members of this home user model objects filter. Home is relations equals self. Hey that's good.
(...)
Then I can use that for authorization logic.
(...)
Essentially.
(...)
It's used in a lot of ways but for example the user should not be able to add an activity for any of the residents in that home.
(...)
Unless they are a member of that home or an administrator system administrator or otherwise.(...) But this is just one step at a time.
(...)
And then.
(...)
For the user model I can probably add a helper function.
(...)
I think one goal here.
(...)
Is to redo the homes page.
(...)
So that this lists instead of all of the homes it lists only the homes that a user is a member of. Unless they're a super and super user.
(...)
I don't know if I should do that in this pull request.
(...)
The system will allow the users to be associated with one or more homes that we can do now. Home page will only list the homes to which the regular user been assigned. OK. I added these constraints.
(...)
Users attempting to access a home profile will get a 403. All right. This is good.
(...)
Properly assigned users will have full access to the home profile including the ability to create activities. All right. So next let's work on that.
(...)
All right. Chad GPT wrote this for me. It's like pretty good and good definition of done. It's a non trivial issue.(...) That's why I didn't label it as a good first issue.
(...)
So we're going to the accounts model.(...) We're going to basically do this. Reverse.
(...)
Let's see what this offers.
(...)
We're using the abstract user model as username first name and last name. Email.
(...)
Interesting. So I guess that get full name is a good one.
(...)
And we're going to add the property.
(...)
Is Adam and has a bit redundant though. It's just aliasing his super user doesn't quite make sense.
(...)
Homes.
(...)
Let's see if it gives us anything here.
(...)
Having.
(...)
It got pretty close.
(...)
But I think if I give it a little bit more context information.
(...)
In the.
(...)
We're getting close to having a circular dependency.
(...)
And the query.
(...)
Basically.
(...)
Well we won't have a runtime dependency on the user model.
(...)
But in import it so I think I can I'm safe to import this.
(...)
And what we want to do.
(...)
And I take this a bit.
(...)
To say we're going to return.
(...)
Get.
(...)
We're going to return a crease it.
(...)
Of home objects.
(...)
Self homes it doesn't exist.
(...)
That's a string.
(...)
Crease it's not been imported.
(...)
So it looks like.
(...)
Co-pilot struggling with this one bit more get it.
(...)
DB models.
(...)
For Chris it will return a crease of homes.
(...)
Hope you're here we go got a home object filter home user relation is self.
(...)
That's it.
(...)
It's a bit hard to read.
(...)
It's incorrect.
(...)
Or.
(...)
It's auto generated.
(...)
So our accounts model.
(...)
Accounts is the app.(...) The model is user.
(...)
Well.
(...)
It's usually something that I'm doing wrong when it's like this level of code.
(...)
Has not been installed. Okay. One thing that probably didn't do.
(...)
Check the settings.
(...)
Install apps.
(...)
It's been installed.
(...)
That's configured.
(...)
We just kill the server and try it again.
(...)
This didn't show up.
(...)
Until I sort of introduced this circular dependency.
(...)
So it could be. It's kind of a red herring it's like an error that's saying one thing but the really problem is something else. It was happened. It was a pretty good appointment the right place.(...) Yeah that was what it was.
(...)
So I created a good circular import situation.
(...)
I think if I just uncomment this line.
(...)
Yep. All right. I just didn't notice that in the terminal when I had it. I take a real quick break refresh my drink.(...) Use restroom and we'll continue here.
(...)
Yeah just figure out a different approach to querying getting the user homes and grouping them by groups which maybe we'll do in a future session but at least I need to get the list of homes on the homepage. All right.
(...)
Excellent.(...) Oh yeah I like that. Thanks. I should below music or have the music continue on that screen I guess.
(...)
I got to figure out my layers of the.
(...)
The OBS set up music background music should continue on the BRB screen.
(...)
Yeah.
(...)
All right. So yeah essentially I just need a way of getting the homes and I think we were pretty close. Earlier I have a query set.
(...)
Essentially I can get the user homes.
(...)
Through the.
(...)
It's the name of that the between. What do they call it. What's Jingle call that. Between. Is it.
(...)
The through model through the through.
(...)
And this I need to type checking so let me see because I'm going to I like to annotate these things. Then I'll import this to. We won't have.
(...)
The circular because it's just going to have that when I'm type checking. Alternatively I could have put this in quotes.
(...)
I like it without the quotes so from home models import. Oh I forgot about that. I could have just put this in quotes. I like it without the quotes. So from home models import. Oh I forgot about that. I could have just put this in quotes. I forgot about that. I could have just put the import in there.
(...)
No actually there it is.
(...)
Even though I'm type checking.
(...)
One of the two.
(...)
It's the type checking one. All right. This is so weird.
(...)
Actually it's not fixing it right away.
(...)
They're going to complain.
(...)
At least I know.
(...)
They return to query set. I'd like to tell it it's a query set of homes.
(...)
But okay.
(...)
So now I have a way to get the homes from the user. So that's good. The reason being is.
(...)
There's an implicit.
(...)
Relationship between the home and the group.
(...)
And if a user has access to a home.
(...)
They have at least access to that home and the group.
(...)
And they can assign it to the container but not necessarily the other homes in the group unless they've been assigned at the group level and they can.
(...)
This is what I have to worry about that.
(...)
In this session but when I'm listing homes.
(...)
Here.
(...)
They should also be listed as.
(...)
According to the grouping so I'll show you just what I mean by that.
(...)
So I don't have any groups to find.
(...)
Sorry these are Jenga groups. I mean home groups.
(...)
So I had group zero.
(...)
And then we can take one of these existing homes or.
(...)
And assign it to group zero.(...) Maybe a couple of them doesn't quite matter. But the main thing is now when I refresh.
(...)
Same data but.
(...)
The group is visible and the reason for that is these homes in our original prototype.
(...)
Typically have 15 to 30 residents per home but they could be organized in a like a campus.
(...)
With.
(...)
You know.
(...)
10 or 20 homes or more even.
(...)
Grouped into larger buildings. So it's essentially it's an institutional care home care facility care campus is really large. So yeah we just needed that so it aligns with the mental model. How the organization sees the care system. So let's just say we'll add home three.(...) To the group as well.
(...)
Now here's the deal.
(...)
On this page I need to show just the homes.
(...)
Yeah just the ones where I'm a member and if they happen to be in within a group then I would show the group but not the homes where I'm not a member in that group.
(...)
Probably making this sound more complicated than it is. Let's just take a look at this homes view.
(...)
Let's see what I can commit so far.
(...)
So I think we're good on the home user relation. I did add those.
(...)
I forgot to commit them.
(...)
I see.(...) So let's go and commit that home user relation.
(...)
Then I'll add the methods separately.
(...)
And my linter.
(...)
User. And to find.
(...)
So I just need to also include.
(...)
This.
(...)
And.
(...)
This is pretty good.
(...)
There we go.(...) So now I got get user model I've got the user model.
(...)
And we should be good.
(...)
Yeah.
(...)
And then.
(...)
Members will work on the access control in a moment.
(...)
I forgot to commit my register function and get full name but I'm just going to do that.
(...)
As a bonus commit.
(...)
Now we're not using type checking though.
(...)
So I'm not going to commit that register the model.
(...)
We might eventually disable the Django admin.(...) But for now it's very useful in development. So I'll revert this change since it's not being used.
(...)
Yes bonus commit.
(...)
What's going on.
(...)
I'm just having some troubles getting this I need to get the query set in there.
(...)
Now we're good to go.
(...)
What did I do.
(...)
Let's get some feedback from the pre commit.
(...)
Interesting.
(...)
So it is just going to not let me do that.
(...)
Can I do that homes on home.
(...)
Any.
(...)
Hey Eddie thanks for the follow appreciate it.(...) Very cool. Well we're getting closer to our following goal.
(...)
Nice.
(...)
I think the emoji bomb makes my system pretty slow. Maybe not. Maybe it's all right.
(...)
We were able to commit this but I'm not liking it. It's still saying it's going to return a query set of any.
(...)
Something is fishy but OK I'll take it. I'll push these up to get real quick and link in the chat.
(...)
This poor question case you want to check it out.
(...)
You can see at the bottom of the video here to the right.
(...)
Is the source repository on GitHub.
(...)
I'm currently working on this port is 86.
(...)
So in case you're just tuning in.(...) This way you can see what we've done so far.
(...)
Very cool. So now we're going to take a quick look at this home page and try to get this same.
(...)
So I need to add my user to home one and three.
(...)
And essentially the same view.
(...)
But based on just the ones that my users associated with later I'll add the admin privilege since I'm a super user I should see everything. But home is one and three so let's go to the home user relations.
(...)
Make sure the server is running.
(...)
Reload home user relations. Now I've got.
(...)
Me the object home to is already there.
(...)
So that'll be good. We'll have one home that's not in home group and maybe one that is in on group is fine.
(...)
For now.
(...)
Now when I go over to this homes view we'll see how this is constructed.
(...)
I don't quite remember.
(...)
So everything is new.
(...)
So let's take a look at the outline.
(...)
We've got a home group list view in a home detail view. So what we want is a home group list view. This is a list view more or less. I've overridden the context of data here and all we've done is pretty straightforward. We get a query set of home objects. So this is actually.
(...)
And then filter them and return them. And I do the grouping in the template. Very good. Very good. But.
(...)
I need to get the request user and I can't remember does Django.
(...)
Django list view. I have a geek context function data function that's going to give me some data. Let me prepare some data for the template that's not already there. By default Django is just going to give me a list of homes and home groups.(...) But I didn't want that. I wanted to do my own grouping.(...) So we were overriding this context data.
(...)
And now inside of that I want to get a reference to the user, the request user. And I don't know if it passes the request in here as an argument or if there's something else. In the Django list view you can access the request object and thus the request user in the get context method.(...) This method is part of Django's class based views and is used to pass additional context to a template.(...) The self variable within this method refers to the view object which has a request attribute. So this is the cool thing.
(...)
Self user homes.
(...)
I don't know that I need the objects.
(...)
Home without group.(...) No,(...) that won't work. I see. So it is it's Django is preparing a list of home groups for me. I'm grouping those in the template.
(...)
Home groups variable so I actually would need to override this home groups to get a list of home groups that the users and member.
(...)
And at that point I don't I don't need a list of you anymore.
(...)
In fact, I could just use this.
(...)
Template view.
(...)
So let's go ahead and do that.
(...)
So essentially.
(...)
This is gonna be a bit trickier than I was hoping, but I need to get the home groups.
(...)
Let's just start here.(...) Home group objects all.
(...)
Refine it. First I'm gonna check this home without group. This should now be only the ones I'm a member of.
(...)
This needs to be self request user.
(...)
This is more complicated than I was hoping.
(...)
We'll pull through it.
(...)
Okay, models 22 counts models like 22.
(...)
Small detail so.
(...)
The individual homes is working.
(...)
What's happening here is we're getting all of the home groups.(...) All of the homes that are in a group, even the ones I'm not a member of. If I look it's a bit subtle, but I'm only member of homes one and two.(...) And we have home three here. This shouldn't be in the list. It's because it's in the list because we're just working in the view.
(...)
I'm getting all the home groups and then for each of the home groups where you are.
(...)
Which is on one home group we're iterating over all the homes with that group.
(...)
So I actually need to do
(...)
is get all the homes with group to the invert should inverse inverse.
(...)
And then and then
(...)
either group them here group and sort here or group and sort the template.
(...)
Let's see what copilot do.
(...)
Maybe not the group just name just the group name is fine actually. Let's see what happens.
(...)
Okay, so it's just going to.
(...)
Iterate over them.
(...)
All right now we got nothing.
(...)
Let me check my home model make sure this is correct because this was all just generated by chai GPT and it's just doing its best bet. Best effort, but it doesn't have enough context usually to really help.
(...)
So I have to very carefully review everything. We do have the home group there. So from the home with the home group that is correct.
(...)
We know that that's working. So if home home group dot name is the next thing. So home group has a name that is correct. What I should do here is use the debugger.
(...)
And let me check my template to make sure I'm using the correct template variable that could be the core problem. So if I go to the home group list.
(...)
Home groups. That was the thing.
(...)
Home group. Then we're going to set it. Then we're going to append to it.
(...)
Okay, we got the group but now not the homes. Okay, we're getting close.
(...)
Now it could be that my home is referring to the wrong thing. Home and home groups.
(...)
Yes, I think my iterator is wrong here.(...) So if you look at this data structure a little bit closer.
(...)
So we're creating a home group's dictionary.
(...)
And for each of those, we're creating a key.
(...)
I think this should be a list.
(...)
Because essentially query sets behave like lists their intervals whereas a dictionary is iterable but you have to iterate over the keys or values.
(...)
I don't think this is going to necessarily fix it. Let's just refresh this to see. Okay.
(...)
So our home groups.
(...)
Oh yeah, I see why that won't work.
(...)
For this one, it might be good to use the Django regroup function in the template.
(...)
Or continue to read this approach.
(...)
And then restructure it.
(...)
It has a list, so I can iterate over it later.
(...)
So I do this items is going to get them both and two people and where's my template expect so I was basically say.
(...)
Group name.
(...)
Whoa, hey, Zoki-wee, thanks for the follow.(...) The emoji bomb.
(...)
I think this will get us a step closer. So essentially I'll have a dictionary for each group.(...) In that way in my template I can(...) be more explicit in the homes. I'll iterate over those. So this will be a string.
(...)
And this will be a list of...
(...)
Anyway, I'm not going to add anything to that. It won't work. What am I thinking?
(...)
Alright, so let's start here.
(...)
Home group name. Home group group name.(...) Home and home group homes.
(...)
Pretty close.(...) Let's see what happens.
(...)
Didn't get it, didn't get it.
(...)
I guess we're just starting a clean template segment.
(...)
Huh.
(...)
I went the whole mile. It did the whole thing.(...) ZJ, have you looked into getting multiple monitors? I'm sure you were here.
(...)
Yeah, I have a monitor here and then my work monitor is over here. So yeah, that is a crucial one. That's true.
(...)
See what happened.
(...)
So it's pretty much the same thing. Okay, debug time.(...) I'm just guessing too much, right? We have the debugger, let's use it. Boing, boing, boing.
(...)
Too much guessing. I'm going pretty far.
(...)
So before we return to context, let's just check everything out and see what this looks like.
(...)
Yeah, it is.
(...)
Hitting this little red dot here and then pressing debug. Make sure I got my correct debugger. There it is.
(...)
Play.
(...)
And then,(...) start it up, refresh, boom.(...) Cool. So what we're after here is what is this home group with the home look like?
(...)
It's looking good actually.
(...)
Has a group name and it has only one home. The data is correct. What am I doing wrong in my template?
(...)
And this is a home instance, right? So it's representing a home class.
(...)
Okay, so the data is there. The data is there.
(...)
The template
(...)
isn't. Boom. Let's put them next to each other.(...) We know the home without groups one is not having a problem. I'll add my little markup later.
(...)
But for home group and home groups,(...) end for.
(...)
Can we just see without anything else?
(...)
Group name.
(...)
Right, I think that should work.
(...)
The issue is I've got my view code has gotten more complicated.
(...)
So now that I've assigned users to homes, I need to list the homes on the home listing page.
(...)
That works. I can just list all the homes that the users are assigned to, but our data model has a level of hierarchy where some homes can be grouped together.
(...)
And so I need to reassemble the homes with group.
(...)
Okay,(...) let me put it down here. How's this?
(...)
It's supposed to have a ducker though. It's supposed to have a side chain.
(...)
Compression applied to the music. But can you still hear the music? I think it's nice to have the music.(...) But I don't know if people turn it up to hear the music and then my voice is real loud, if that would be really annoying. So I sort of tried to balance them a little bit.
(...)
But turn it down. So here we should at least get the group name for each of those. So let's see, this is work.(...) I have a plate.
(...)
Nothing.(...) Okay.(...) Let me remove the breakpoint for a minute.
(...)
Make sure I'm using the... Oh, you know what I didn't do is put it in the template context.
(...)
Damn.
(...)
It happens.
(...)
Now,(...) play that funky music. Oh man. Yeah, the attenuation.
(...)
So is the music ducking my voice or is my voice ducking the music? Because it should be that the voice is not the voice. It's the voice. And then I can just do that. And then I can just do that.
(...)
Because it should be that the voice...
(...)
If I go to the filters, for the background music,
(...)
I've got a compressor, sidechain ducking source, audio input capture.
(...)
That probably wasn't working at all. Okay.
(...)
Well, but yeah, I don't know.
(...)
I'm not really super confident about the OBS built-in plug-ins. I had a compressor on my voice, but it was also making it sound like I was under water.
(...)
So...
(...)
Maybe I have to have a...
(...)
And a threshold where the...
(...)
Music's actually getting above. It seems to be around -45 dB.
(...)
Well, yeah, let me know if the music's still too loud. I put it down pretty low. But I'd like it to be audible at least.
(...)
Oh, now I have to save my view. Dude.
(...)
It's getting late. It's 10 p.m. I'm getting tired, so I'm making easy mistakes. Yep.(...) Yes!(...) Did it!
(...)
I'd like for this bar not to be there on the last one when we're iterating over them.
(...)
Yeah, it's so great. And to have the debugger just like show me what's going on and show me usually the mistakes I'm making.
(...)
Honestly,(...) usually if I'm getting some weird error from Django or like... And especially if I can't to find any other people with that error, then duh, I'm doing something weird. And sometimes the problem is that error is not always pointing me in the right direction. So it can be very confusing.(...) Yeah, like earlier.
(...)
Okay, so this is great. We got the homes working.(...) Let's commit this and then add one little nice touch.
(...)
Yeah, sometimes the error takes reading and sometimes it's like...
(...)
I don't know what the phrase is for this, but it's like...
(...)
The error triggers another error higher in the call chain and that's the one that surfaces to the terminal. But the really source of the problem is something else.
(...)
But yeah, it's really nice on my brain too. And my brain, like I say, is slowly turning to mush. So I need nice developer experience.
(...)
All right, so now we've got this fix. I fixed this model.
(...)
And this is what allowed us to get the homes where the user has been assigned.
(...)
I'll probably need or at least some logic in the view that's going to conditionally return all of the homes for the super user.
(...)
I don't know. Maybe I should add that in this session or later. Oh man, I also need to add unit tests.
(...)
So I'm not going to be able to complete this pull request tonight. It's too late. But I will return to it with fresh attention and everything tomorrow evening.
(...)
But we've made good progress.
(...)
And essentially it's still a list view, but it's not like inheriting from the list view. I'll leave the naming convention.
(...)
Yeah, yeah, you can get your feet wet and react and see how long you can keep up with the changes.
(...)
You know, change is constant. We know that. We've known that for millennia.
(...)
But at some point, you know, you don't want to build your house on sand dunes. What's the saying there?(...) And it feels like JavaScript is like trying to build something while the whole ground is shifting.
(...)
Yeah, that's true. React is JSX in particular, putting everything in JavaScript.
(...)
Craziness.
(...)
CS.(...) Yeah, you don't want to build your house on sand.
(...)
And sand dunes.(...) Yeah, it just does. It feels like building a house on sand. This project in fact was built in the JavaScript framework called Meteor JS. You probably have heard of that one. It was popular for a while.
(...)
And it's still around, but there's several problems with Meteor. One is they banked too heavily on MongoDB because they are real heavy into reactivity and Mongo operation log was the source of their reactivity.
(...)
However, as you know, most web applications have a relational data model.
(...)
And that meant defining schemas and relationships using downstream contrib libraries. So, you know, Meteor didn't include any support for defining schemas or relationships with the assumption that you don't need those. But I beg to differ. And you end up in like a situation where your schema is actually, it still exists. And as it doesn't go away, it's just spread throughout your whole application, business logic and stuff, and maintaining backwards compatibility layers and things like that.(...) The other issues that didn't really come with some critical batteries, including a router,(...) like page navigation was sort of an afterthought and left to the community. It was kind of a weird thing.
(...)
But there were some other crucial batteries that weren't included.
(...)
Ah, okay, I can fix that.
(...)
So if I do the background music filter,(...) I believe if I increase the release time to like half a second,
(...)
it should be more smooth.
(...)
How about that?
(...)
Yeah, that makes sense. And I do kind of want it to be a little bit loud,(...) roughly the same mix as my spoken dialogue. People don't have to like turn up and down. Because I think it's nice to hear music when it's quiet.
(...)
But my voice shouldn't be overpowering.(...) Or they should, yeah, mix.
(...)
So it's peaking at -25 and my voice is clearly going to be louder than that. -15.
(...)
But is this a little bit better mix?
(...)
But long story short, the Meteor devs eventually sold. They had an exit strategy. They went on to develop some interesting projects.
(...)
Meteor did have a lot of potential, but it got swept away with React and then later got Vue and NUS felt and all these support for other. It's more framework agnostic on the front end, library agnostic. But it originally started with Blaze.(...) They even had - you could build an Intuit app, including Cordova support. It was pretty cool.
(...)
A lot of potential, but the reactive development model was really fun. Great for prototyping, but it just was building on sand and our project wasn't sustainable.
(...)
So now we're moving back to more sustainable foundation. While I think still being able to build with innovative tools, I'm really looking forward to experimenting with some more asynchronous code in Django and potentially HTMx as well as potentially improving the user experience by adopting a more comprehensive UI component library.
(...)
Some good stuff on the horizon.
(...)
Now the decision being that I don't have to go to sleep anytime soon. I can stay up a bit late.
(...)
I think I'm going to add a condition in the view that if I'm a super user, it's going to show me everything. That means that's going to be a bit tricky.
(...)
That won't be tricky.
(...)
Let's take a look at it.
(...)
And then the last thing I think I'll do,(...) maybe unit tests,(...) but will be to remove this divider at the end of the list if it's the last item.
(...)
Let's take a look at the view though.
(...)
So essentially I just need two query sets or yeah, it's two queries. It's one homes with a group and one homes without group.(...) When the user is not a super user, it's going to get it from the user model. When the user is a super user, it's going to get it from the homes and home group models. So that's only a subtle difference. I worked on a project at Django REST framework. It's good. The issue is that it felt pretty slow versus others like fast API.
(...)
Yeah, that's the problem. I think a lot of it is because it's not asynchronous and it wasn't when the Django REST framework came around.
(...)
Async support wasn't there, but with Django 4.25, we're getting a lot better.
(...)
And I think they've gotten all the way to the ORM layer where just a few of the database operations are synchronous, but even in the ORM there's asynchronous operation.
(...)
But what do you think of that Django... Oh,(...) alternative and what is it called? Ninja.
(...)
Because for this project, more than likely going to be adding a REST support.
(...)
And we're not going REST first or API first development. That's a bit overkill. Just like I don't do really test driven development. I'm not opposed to it. I don't think there's so many complications with writing tests or writing API endpoints.
(...)
It doesn't make sense until you've made more headway in writing your app code and knowing how the app works because a lot of things I'm just figuring it out.
(...)
I'm not really ready to write an API for it. Or I don't know what kind of a unit test I would write. But what do you think about this Django Ninja? Have you looked into this one?
(...)
Because I think it's built around async and pydantic, so it's essentially like the fast API for Django.
(...)
JSON scheme and open API, so it's really...(...) And I guess it's not Django,(...) although it has Django the name.
(...)
Django friendly.(...) I don't know. Yeah, so I guess it is Django.
(...)
Yeah, let me know what your thoughts are if you peek through it.
(...)
But you can see it's got a lot more concurrency because it's using asynchronous code than Django and Flask.
(...)
But yeah, I mean, we have...(...) We use fast API. We work and have a pretty good experience with that.(...) All right, so then all we're going to do, though, here...
(...)
Is just get a reference to this user first.
(...)
There we go. So we keep typing self request.
(...)
I'll clean it up later. We'll see if this looks...
(...)
Legible.
(...)
But essentially,(...) if there's superuser, do that.
(...)
And some superuser. I see everything.(...) Good.
(...)
Man.
(...)
It's a bit of a heavy function, though. It's doing quite a lot, isn't it? What I can do is...
(...)
Regroup homes or something like that.
(...)
And just move this up here a little bit.
(...)
And I think it's just going to take...
(...)
For home and homes now.
(...)
And then it'll return.
(...)
And hopefully I'll just work.
(...)
Yeah, same thing.
(...)
I'm going to use Bootstrap on a quick apps. But I'm tired of how it looks myself. Yeah, that is one of the common concerns with Bootstrap is it is fairly generic. It looks nice and appealing, and it does help you iterate pretty fast. It's under active development.
(...)
Like last week, it had a contribution. It supports accessibility and all sorts of... There's a lot that has gone into this framework.(...) And it is tapering off, but it has at least two core developers who have been active in the last, let's say, year.
(...)
And it's had several significant contributors beyond, let's say, 25 commits, beyond 10 commits. That's, in my book, fairly significant.
(...)
It's sustained. So that's a good sign.
(...)
Tailwind, what do you think? Let's take a look. This is just one way of looking at it. But when I'm thinking of open source sustainability and longevity are two things that I've learned to be very appreciative of.(...) Tailwind hasn't been around a while, but it's been fairly sustained since 2018. So not as long as TWIBs, but I mean, it's good.
(...)
Yeah, in 2023, it had several maintainers. So that's a good sign, you know.
(...)
Commits yesterday.
(...)
You know, then you look at other details like there's CIs in place. That's good.
(...)
Popularity, the documentation, you know, excellent. I think Tailwind is excellent.
(...)
So yeah, I think these two projects would be the main ones I would even consider touching on a new project.
(...)
And I just happen to go with Bootstrap.
(...)
For simplicity, and I don't really want to think, I want to think at the component level, the UI component level, and not worry too much about making my own UI definitions at this point of the project.
(...)
Contrast that with Bulma.
(...)
You probably heard that one.
(...)
Three hours ago. All right. All right.
(...)
But sometimes that can just be something like a dependent upgrade or something like that. But about the same age as Tailwind, development is like almost. Well, they had maybe like a really high development level. Let's see.
(...)
High number of commits. So this had 200 though. So that can kind of dwarf the later ones. But this one had only 80. But let's take a look at just 2023.
(...)
Basically one person. And I think that's the story of Bulma. It's like one person, one passion project.
(...)
And based on that, I would not bank on Bulma.(...) Just you don't have the same diversity and stability and diversity matters.
(...)
Also some of the Bulma.
(...)
Default types I think were questionable. The browser overrides.
(...)
So yeah, I would on my projects be looking at Tailwind and Twibs. And I went with that.
(...)
Yeah, I can see the appeal and it does. You know, when you get enough of the definitions and you get familiarity with it, you can make some really nice stuff.
(...)
I'm just not writing enough reusable code and my templates. I don't want to, you know, there are even with bootstrap classes, I'd like to say this is a container or this is a card.
(...)
And I know that's antithetical to the sort of the Tailwind philosophy, but even though it now supports and there are component libraries built with Tailwind.
(...)
I kind of like being at this level. I haven't encountered any scale issues. So maybe my projects just haven't been big enough where this would start to become an encumbrance. And that and I haven't really tried to customize bootstrap too much too, because I know that that's a common complaint.
(...)
So yeah,(...) maybe I'll take another look at Bulma. I mean, at Tailwind, but I'm really gonna look at this Nord Health design. This is cool. Check this out. If I didn't link it earlier.
(...)
Yeah, it is quite and I'm not really a designer. I just want something that looks decent and we can move on.
(...)
And if we get a designer resources, then we might look at, you know, something with Figma support. This has Figma support and dark and light things out of the box. So it's like really looking good.
(...)
You know, and at some point I might have to just bite the bullet like it. And that was another thing with Tailwind is I would pretty much have to start working with NPM.(...) You know, in order to do like, what do you call it? Tree shaking, essentially the styles that were unused. Otherwise I would install Tailwind from CDN and have like the whole thing. And I think it's bigger than bootstrap at that point.
(...)
I don't know. I've never heard of that. What's Jasmine?
(...)
Interesting. And then there's a drop in app to jazz up your Django admin site with plenty of things you can customize, including a built in UI container. Yeah,(...) it would be really cool to get more mileage out of the Django admin in particular to use it for non tech users like non administrative users.
(...)
And that's why on another project, we use Wagtail CMS. It is really good.
(...)
Like the design, the user experience, the project is maintained very actively, the community is really good. And it's basically WordPress for Django. It's used by some really prominent organizations.
(...)
It's built on modern, so to speak,(...) content management paradigm, this block based, which essentially is the way HTML is blocks of content, like types, you know, dividers and paragraphs example or UL. So it's natural that we have emerged this block based CMS paradigm as well. It's kind of reflecting the medium is the message in a way.
(...)
Wagtail is in cost. Nope, it's fully open source. There's no premium or freemium.
(...)
There is a consultancy that called the torchbox that are the main developer. Look at this nice dark and light toggle. They are the main developers.(...) And if you want their services, then yeah, that would cost.(...) But there's no there's no gimmick Wagtail is fully free, you can just use the whole thing.
(...)
There's no premium modules or plugins.(...) And even torchbox is like super active with community support as well, like on Stack Overflow or GitHub, like super forthcoming and never never have they asked for us to pay any subscriber fee for premiums or anything like that. We've been using them for five years and another open source project.
(...)
Yeah,(...) it is really good. And it's only getting better. And especially like after in recent releases, they have a big focus on accessibility and usability documentation. So they're like really a full fledged project.
(...)
When we were originally starting this other project where I'm using Wagtail CMS, we were looking for other Django CMSs and we did look at the Django CMS and also mezzanine.(...) But the Wagtail just really stood out at that time five years ago and it has only gotten better.
(...)
Wagtail and Gitpod, that's kind of cool.
(...)
Yeah,(...) and they really are focused on usability.
(...)
We migrated over from Drupal and there's a lot of custom migration scripts that wrote to do that. But the Wagtail migration path from WordPress is much more straightforward if you're if you're needing to migrate.
(...)
So I think with things like Wagtail, well, it's so easy to customize and define bespoke landing pages and the navigation menus. I haven't really ever looked back.
(...)
Admin LTE. Yeah, that was another project we used with a meteor one. All right. All right. We're getting far along. We're getting far along.
(...)
So now that our view logic is more complicated,(...) our test suite is going to be more complicated.
(...)
I'll refresh my water and clear my mind for a minute. I'll come back,(...) commit the
(...)
commit this and I'm going to write a test suite for this view. We'll test both regular user and super user scenarios where the users are a member of multiple homes and at least one home with a home group.
(...)
Hydrate rewards.(...) How do you do that? I can set that up. I'm trying to add little improvements to this stream for sure. Like the layout and stuff like that has changed over the last couple of weeks.
(...)
What's the thing? Like if I hydrate Twitch.
(...)
Hydration. No.
(...)
Okay. And if somebody gives me channel points and I've got a drink, so that could be dangerous.(...) You can get water toxicity pretty.(...) I don't know pretty fast, but all right. Let me take a look.(...) Twitch channel points. So you see them somewhere. I call them programmer points.
(...)
Yeah.(...) As long as I can control the usage a little bit on the water, I do try to stay hydrated lately.
(...)
But I'm going to be right back. I'll commit this when I come back. I'm going to hydrate.
(...)
But now I think I'm balanced channel point guide for creators. I'll have to look at the hydration points. Some reason my Firefox isn't opening up.
(...)
So.
(...)
I don't know if I just added this whole thing or just refactored it. No, I moved it to a helper and then.
(...)
The regroup helper.
(...)
What is called that?
(...)
So again, if you're just tuning in and you want to see the changes made during this live stream.
(...)
Here's the pull request. Definitely would use channel points for stretch break QA, etc.
(...)
All right.
(...)
I'll have to see what other streamers are doing with their channel points.
(...)
But let me make note of this.(...) Somewhere. I don't know.
(...)
All right.
(...)
Got those.
(...)
Let's just say what are some.
(...)
I got to assume that the model knows more than me.
(...)
Here are some creative ideas for rewards. Choose the next game. All right. Q&A time. Gameplay challenges.(...) Voice modulation.
(...)
Tutorial or tip session. Social media shout outs. Channel VIP status.
(...)
Dang.
(...)
Fitness challenge.(...) Oh yeah, I could do that actually.
(...)
Back cameo.
(...)
Cost play music time. I got to watch the copyright strikes and provides a story. Personalized thank you note. Highlight real participation.(...) Wow. These are some interesting ones. What do you think are your favorites there?
(...)
I'll put this on my desktop.
(...)
Okay, you can tailor the questions.
(...)
For yourself and your theme.
(...)
Let me change that. [typing] So we're not playing games, it's the primary activity. I know there's many game streamers out there, but there might be something more specific for live coding. Coding tutorials,(...) live coding projects, code reviews, pair programming. Hey, that's kind of cool. I've been thinking about that because you can invite people on to the stream.
(...)
Somehow you do like co-streaming, that would be tight.
(...)
[music]
(...)
And I've already done an on-stream code review, as well as I opened a couple of pull requests to a viewer project.
(...)
[music]
(...)
Wow, there's a lot of these.(...) I'll just put all these in a scratch pad and think more about this. This is a new world, I didn't even realize that this is possible.
(...)
Good suggestion, thank you very much.(...) [typing]
(...)
Yeah, that's true. A lot of these are pretty specific.(...) Probably most of them I'll throw away, but it's just good to get the ideas flowing and to learn how people are improving the stream and the engagement.(...) Basically, it's beneficial for people who are hanging out and people who are having fun and stuff. That's the main goal here, that's why I'm streaming. Otherwise, I can just sit and program and work on these open source projects. Sometimes I just do that, but I don't feel motivated or something like that. I'll just do the coding, but I thought it's more fun oftentimes to hang out.
(...)
This is nice.
(...)
A little improvements like this, adding the background music, a little bit of aesthetic changes.
(...)
I'm opening a lot of suggestions like that.
(...)
Well, now let's have some fun writing unit tests.
(...)
[typing] Okay.
(...)
I think actually if I run my tests...
(...)
The fact that there's no failures is a bad sign.(...) I've made a big change.
(...)
Mmm.
(...)
No, that's a bad sign.
(...)
[laughs]
(...)
Because even as the super user, while I have access to all of these homes, the structure changed subtly. If we look at the templates, of the context, in other words...
(...)
I thought I had a pull request for this.
(...)
Okay, I just haven't linked it to the issue. Sorry, this is the actual pull request.
(...)
62.
(...)
But if we look at my context, just by virtue of checking out the template...
(...)
We can see that I'm iterating over a dictionary now. Kind of bespoke keys, whereas previously I was iterating over entities and a query set.
(...)
But here regardless, I need to write a unit test. This part of the project is not covered.
(...)
So one thing I like to do is get some help from Chad GPT.
(...)
[music]
(...)
And essentially, if I paste in my models...
(...)
So here I'll need the user model,(...) the home model...
(...)
It's probably enough context...
(...)
...to prompt it...
(...)
Maybe the home group model as well.(...) To prompt it to...
(...)
Help me write a whole test suite. This is cool. Let's see how far we can get.
(...)
Let me close down some stuff real quick. Twitch hydrate challenge. That's good.
(...)
Good idea.
(...)
I need to write a comprehensive test suite for the following view.
(...)
But I'm going to give it a little bit more context here.
(...)
Given the following models...
(...)
Because now our context window is like 8,008K, so that means I can pretty much...
(...)
Paste this whole application in there. Not quite, but I'm getting there.
(...)
So here's the home model. So we'll need the home group...
(...)
And the home, but the home is massive.
(...)
So I will just...
(...)
Because I have a lot of helper functions.
(...)
Mainly for the analytics. This is an analytics-heavy application. So if you're interested in data visualization...
(...)
This is the place to be.
(...)
And I'd appreciate any advice.
(...)
Right now I'm sort of shoehorning an analytical application onto a relational database.
(...)
And it's working out, but eventually I'm going to have a reckoning probably.
(...)
I don't think we were using the members.
(...)
So I don't really need that. It's essentially if I just...
(...)
Give it just enough.
(...)
The home group.
(...)
And the account model.
(...)
Because there's a little bit...(...) This home's helper is the main thing.
(...)
And then I don't need the full name or really the "stir". That's just kind of wasting my context.
(...)
And the verbose name.
(...)
Probably not super important. Should know about... I believe it knows about the abstract user.
(...)
So same thing. I'm just going to pare down a little bit.
(...)
And just tell about the need. And not make any specific requests here. Just say...
(...)
"Here's what I'm trying to achieve."(...) Usually I'll get back,(...) at least step by step, how to write this test suite as well as the specific test scenarios I should be targeting. The pare programming on the stream. I think that's one of the things I'll use the channel point for. That would be fun.
(...)
Okay, so this is good. It's already breaking it down. To write a comprehensive test suite for your home group list view.
(...)
And the regroup homes by group. Yeah, you probably should test this separately. You need to cover various scenarios and edge cases. Your test should verify that the view correctly handles different types of users. Like super users and regular users. And that the homes are properly grouped by their home group.
(...)
I do... and to do this I should have mentioned...
(...)
We have a bunch of factory methods that will be useful here.(...) So create the test models. First you need to define test instances of user, home, and home group models. Make sure to create homes with and without home groups. And assign them to different users and groups. Yep.
(...)
Test the regular user and the super user.
(...)
Include homes without groups and empty groups. Okay, now it's getting to the code. This is really good.
(...)
So it actually got me probably 40% of the way there.
(...)
It's a crucial 40% because it's helping me think holistically about this.
(...)
And it's giving me a skeleton of a test suite.
(...)
So what I can do now is iteratively improve this.(...) So if I mention, for example, we have factories.(...) Factories...(...) factories...(...) for home.
(...)
And I'll create a home group factory.
(...)
And I'll switch to syntax because that way if I have the model explicitly in here, this will give Copilot a little bit of information.
(...)
So I'll make a suggestion here.
(...)
So this is all predicated on having a really good test setup.
(...)
So we'll start here. Then writing the test cases will get a lot easier.
(...)
So we got a user and a super user.(...) A couple of home groups. We really only need...(...) we want to have an empty home group and a home group with home or something like that.
(...)
Alright, so we got a really good start.
(...)
So let's move over to the test code.
(...)
And I do have some tests.
(...)
So I'm not like totally skimping on the tests.
(...)
Mainly the model.
(...)
And some residents with activities, but I haven't tested the view.
(...)
Until now.
(...)
So we've got the test case.
(...)
Let's get our imports up there.
(...)
Let's do these one at a time.
(...)
Django_contrib.
(...)
Django_test comes after that. I'm not sure why my imports didn't get sorted.
(...)
And then factories.(...) And that is true. They're in the same...
(...)
Here they are in fact.(...) Home group factory.
(...)
And then we're going to grab the user model.
(...)
Yep. And Copilot also knew that. So on the same page. I sometimes am curious if Copilot and GPT-4 somehow know about each other. They're the same entity. Okay, so we've got a user and a super user.
(...)
And what I want to do is set up a...(...) I'll be explicit about my naming.
(...)
So the idea here...
(...)
Is just going to have one without a home.(...) I really don't need necessarily...
(...)
To my knowledge, I don't think I need a second one. Just a home group with home. And a home group without home. I'm trying to think through these test cases a bit more.
(...)
Likewise,(...) we have a home with group and a home without group.
(...)
Format.(...) But...
(...)
We need a home.
(...)
Where's our without group?(...) I'll call it user home with group.
(...)
Or...
(...)
Yeah, that's true. Have you tried any plugins? Like these VS Code ones?
(...)
I'm also a bit sketchy about the plugin authors. I don't know how much you can trust.(...) I don't know. I'm not saying people have...
(...)
Inherently bad intentions, but some people do.
(...)
And I just don't know any of these people.(...) And you can audit the code, of course. The same thing, I'm still a bit skeptical about Docker containers too. We use those like pervasively. I don't think we've got audit them as much as we should or could.
(...)
They run secrets and all sorts of things.
(...)
I have not tried any of these extensions. I know that Copilot is powered by GPT, but I suspect it's sort of in between GPT 3.5 and 4. It's not quite there.
(...)
What I get out of the chat interface.(...) So we need a home with group.
(...)
Let's just call it home without user.
(...)
And this is interesting.(...) This won't work.
(...)
You can't just assign the user here.
(...)
So what we need is another factory.
(...)
And then we're going to write the first test case just to assert that this data exists, that it is correct.(...) That's what I've kind of been doing. I don't know how common that is in other projects, but I assert my test data is how I'm expecting it to be.
(...)
I suppose since I have like an interactive to debugger, I don't really need to do that. Maybe it's just a habit I formed.
(...)
So now we need to run over to the...(...) I'm getting tired.
(...)
Yeah, another third party ones.
(...)
So how do we associate users with homes?
(...)
We'll need to define...
(...)
Probably a factory for this. I don't know.
(...)
But the cool thing is with this home user relation factory,(...) it can use sub factories or we can specify it. So that's a good thing about factories.
(...)
So now that we've got this,(...) we will close something down,
(...)
maximize this for the time being so I can just see what I'm doing.
(...)
I guess I could use a wider display or something. It's pretty wide though. It is pretty wide.
(...)
Now we'll use our new factory model.(...) Home user relations factory.
(...)
To associate user with homes.(...) Let's see what it does. Home with group, self user.(...) Home without user, self user. Didn't do it. Not correct. Home without group?(...) Yes.
(...)
I think that's pretty good.
(...)
Yeah, it's essentially a warning.(...) Have a test, more or less let me check my mock data a little bit.
(...)
All right.(...) Right, right, right.
(...)
So what we need to do is actually get the model now.
(...)
Home group and home group relation.(...) Yeah, so getting close.
(...)
My imports there.
(...)
So those baseline tests, the
(...)
other way of looking at it would be
(...)
to see what we're doing. And the super user is not part of any homes, but they will be able to see homes.
(...)
Then we can assert that the homes are in, but I think we're pretty good.
(...)
All right, so now let's feed this back to chat GPT so it knows what's going on.
(...)
So just giving it the current scoop. So when it's going to help me write the remaining test, it's going to know about the context data, my naming conventions that I introduced.
(...)
And maybe just work through the
(...)
test mock data.
(...)
So what I'll do,(...) he's asking to write a revised test mock data.
(...)
To make sure our test mock data mock. Yeah, anyway, mock data is set up correctly for subsequent tests.
(...)
So it's checking accounts, quickly associated home with our home groups.
(...)
Home group with no homes actually has no home associated with it. Interesting.
(...)
Let's see.(...) Good, it ran. Wow.(...) Now.
(...)
I'm thinking we can break this down into basically two remaining test functions, one for the super user case and one for the user case. But let's see what chat GPT thinks about that.
(...)
I'll tell it what I'm considering.
(...)
We should also perhaps create a user with no homes. I mean, nothing will display.
(...)
We're sort of testing that implicitly.
(...)
Or user with homes that home group see it's a bit complicated and there's a lot of lot of edge cases here.
(...)
Let's just ask.
(...)
Make sure our test data is sufficient.(...) For example, having the user that has not been associated with any homes.
(...)
So yeah, I'll just read this a lot a little bit, if it helps.(...) So we're going to test the context data for regular users, the context data for super users, make sure that that's shaped correctly. We've got a function that groups the homes together. So we want to make sure that function is behaving as expected.
(...)
It might be good to just write a an isolated test case for that. If I give it a list of arts, a dictionary with home key values.
(...)
We'll think about that in template rendering, make sure that the correct template is used. And if it renders without errors, optionally check if key elements are present in the rendered template.
(...)
Something like beautiful soup. There's also just some built in Django template primitives that allow you to check or request contains a string or something like that. Access control. Check that unauthorized users are handled correctly, either redirected or shown an error. We don't have access control on this view.(...) Maybe to my knowledge, we don't might have added that like it might redirect to the login page. That's a good point, though. Empty states. So yeah, let's start with the first one.
(...)
Yeah, now I find that if I work in chunks, instead of asking it to like write the whole thing for a test suite that has this many potential tests, I think we'll get a better result.
(...)
Particular because these tests contain dozens of lines, in some cases.
(...)
So that first it's going to log in as the user. So it's using the test client,(...) then it's going to make a request to that view.
(...)
Okay, so I'll have to get the reverse name for that view.
(...)
Just for sure reference. I'm going to say I'll add that in the setup. That's a good thing to add to the setup.
(...)
Self.url.
(...)
Let's add that first. So and import reverse.
(...)
And the name of the view.
(...)
The homeless view.
(...)
That looks good.(...) Oh, wow.
(...)
And then it rewrote the test for me.
(...)
Test context data for regular user. All right, now we can just add this one in there.
(...)
We'll run the test and just see what happens just out of the box.(...) All right.
(...)
This is a pasting error in the problem. Also.
(...)
Did we set the password?
(...)
This is what happens when you copy and paste stuff.
(...)
Yeah, you don't really know what's going on. You have to read it carefully, but it's.
(...)
And that needs to be self.
(...)
I still think there's a lot of room for the person involved in the loop here with the AI to help pair program essentially. It's able to do the bulk of the programming, but concept work and making sure things work as you're expecting it still takes a human loop so far.(...) You know, this is my experience. What about you?(...) You think these Gen AI tools are going to be replacing programmers wholesale in the next five to 10 years, or is there going to be like a symbiotic thing?
(...)
Or perhaps putting us into a new realm or modality, but still needing technology skills in like mindset.
(...)
I'm really getting tired, so I don't want to really read the whole thing, but.
(...)
Comprehensive test case for the context data for super users.
(...)
Creating a comprehensive test case for checking the context data in the home group list view for super users involves verifying that the super user gets appropriate context data, which is like basically everything.(...) This usually means checking the super user can see all homes irrespective of their group association or user association. Depending on your applications logic.(...) Here's how you can structure your test.
(...)
It's going to be a bit more complicated, but.
(...)
There's a bit of a typo there.
(...)
Maybe this seems to be.
(...)
This should be group name, I think.
(...)
Let's try it out.
(...)
And I can't just copy the whole thing here.
(...)
I really should be considering committing these soon, because it's going to be a bit hard if I copy paste everything in and need to roll back a little bit.
(...)
We'll run it, but I suspect there is a typo.
(...)
Very cool on my view.
(...)
Home groups with knit with homes.
(...)
Home group with homes should be home group group name equals group name.
(...)
So this is starting that any so for home group and home groups.
(...)
It's asserting that it's in the home groups with homes.
(...)
It's also asserting that all.
(...)
That's a confusing one. Wow.
(...)
Yeah.
(...)
I guess you just let alone.
(...)
Okay, because we're iterating over home groups. Got it.
(...)
The AI knows the code better.
(...)
False is not true.
(...)
All right.
(...)
469.
(...)
I don't even know what this is saying.
(...)
What if I ask.
(...)
Let's at least check this one.
(...)
So it looks like the.
(...)
This test passes.
(...)
Also not true.
(...)
I love to.
(...)
Step back through these.
(...)
This is complicated and I'm not sure that I gave enough context.
(...)
For GPT to really figure this one out.
(...)
My home without group homes with group.
(...)
All right.
(...)
We can use debugging here.
(...)
Test debugging. So I have actually.
(...)
A debugger profile set up for just this purpose.
(...)
Yeah, I guess the unit tests aren't so exciting.
(...)
Lost all the viewers.
(...)
Let me edit this.
(...)
Don't get this done. This is really good.
(...)
Really good progress.
(...)
And we're testing.
(...)
Home tests.
(...)
Home group list view test.
(...)
So now if I run my debugger should only run that one. Test suite.
(...)
All right.
(...)
So.
(...)
I know this is gonna return all the home groups.
(...)
We have one. We're home group.
(...)
That any group group name equals home group name for group.
(...)
Okay.
(...)
So the premise is wrong here.
(...)
We can't assert that for every home group.
(...)
That it has homes.
(...)
Because I'm not sure we set that condition up.
(...)
In fact we probably shouldn't test for that.
(...)
But more what we can iterate over is this.
(...)
All right. So we've got the group name home ID or home for.
(...)
If I look at the home group with homes.
(...)
We've got only.
(...)
Group one.
(...)
Home group group one. Yeah. All right.
(...)
Name is group one.
(...)
So that this.
(...)
This home group does exist inside of the.
(...)
The list by the key group name.
(...)
All right. So we'll play that.
(...)
But.
(...)
Home group three.
(...)
Does not contain a home.(...) Right. So would not be in that group.
(...)
That's cool. So.
(...)
Since I already have references here.
(...)
I can make the assertion without the any statement.
(...)
Or at least without iterating over.
(...)
All home groups.
(...)
Sort true.
(...)
Let me just run it here. It's a bit faster now.
(...)
So that was it. That did cause it to pass. Okay.
(...)
Yeah.(...) So this group without home should not be in the home group with homes.
(...)
Here we go.
(...)
And the next challenge.(...) More difficult that the homes in the context are correctly associated with the home group.
(...)
All home in group.
(...)
And it's no longer exists.
(...)
Oh it does.
(...)
Let's see if I just delete this.
(...)
And ask for some help.
(...)
From Co-Pawlett.
(...)
And the inverse.
(...)
(soft music) - Yep, so we had the case now where the home without the group is there.
(...)
(soft music)
(...)
(soft music)
(...)
I wonder if this can be made more readable.
(...)
(soft music)
(...)
(soft music)
(...)
(soft music) (soft music)
(...)
Group at home.
(...)
(soft music) (soft music) (soft music)
(...)
(soft music) Well, that's a little bit better. It's still.
(...)
(soft music)
(...)
Pretty hard to grok. (soft music)
(...)
(soft music) It's working. So now I'm gonna just sort of pollute the context window
(...)
with the result of our tests to make sure that chat GPT has been updated.
(...)
It's all the work so far.
(...)
(soft music)
(...)
(keyboard clacking)
(...)
So some of the things had to be rewritten a bit.
(...)
I think there might be one more test case.
(...)
(soft music)
(...)
(soft music) (soft music)
(...)
(soft music) (keyboard clacking) (soft music)
(...)
(soft music) (soft music) (soft music) (soft music) (soft music)
(...)
(soft music) Hmm, this is pretty comprehensive.(...) Let's see if this runs. I don't think I ran it.
(...)
(soft music)
(...)
(soft music)
(...)
I'm gonna commit this as an initial test suite.
(...)
(soft music)
(...)
(soft music) (soft music)
(...)
The reason being,
(...)
I believe adding this more comprehensive setup is gonna throw a wrench in the works a bit.
(...)
While still opening the door for testing additional scenarios that would be potentially edge cases that crop up.
(...)
(soft music)
(...)
So we'll need to revise our test mock data as well.
(...)
(soft music)
(...)
(keyboard clacking)
(...)
Let me just see if this runs,
(...)
or passes at least.
(...)
(soft music) It does, the new data didn't alter that.(...) (soft music)
(...)
(soft music) (soft music)
(...)
(soft music)
(...)
(soft music)
(...)
I'm 500. (soft music) Surprised I didn't break earlier though.
(...)
(soft music)
(...)
(soft music) (soft music)
(...)
(soft music)
(...)
Well, let me just take this one step at a time.
(...)
I can't make this out, that's what I was thinking it would
(...)
cause some problems in the remaining tests, that's all right.
(...)
(soft music)
(...)
Also,
(...)
indentation got screwed up.
(...)
Dang it.
(...)
(soft music)
(...)
Yeah, it's now both of these have failed, which is cool.
(...)
All right, I'll just ask for revised update test case.
(...)
(soft music)
(...)
(soft music) It's just, I think just kind of changing that, but there could be a few more assertions we need to make.
(...)
(soft music)
(...)
(soft music) (sniffling) (soft music) (soft music) (sniffling) (soft music)
(...)
(soft music) We'll just run that test in isolation.
(...)
Well, not isolation, but.
(...)
All right.
(...)
(soft music)
(...)
(soft music)
(...)
There may be some duplication in these, but
(...)
well, it should show all homes and all groups.
(...)
(soft music)
(...)
Except the empty room.
(...)
(soft music)
(...)
(soft music) (soft music)
(...)
Hey Rebel,(...) thanks for that subscribe. Appreciate it, very cool.
(...)
I probably need to switch between the emoji bomb and
(...)
the other little star thing. Very cool, thank you. Hey, how are you doing?
(...)
Making some progress here. Oh, okay, what did I do wrong?
(...)
544.
(...)
Ah, din din din.
(...)
With the help of Chad GPT, like crazy. This is a massive test suite.
(...)
Man, that is so remarkable.(...) It can just juggle so much context.(...) I'm doing good, I'm pretty tired. You got two minutes to spare, all right. Nice to have a break. Are you working on something or what are you up to today?
(...)
Been, this is my sixth hour. Wow, this has been a six hour live stream, I didn't realize that.(...) And I had a full day at work as well, crazy. But I got really motivated by this project. Legal stuff, oh man, it's always a bummer.
(...)
I'll be out some assistance with that.
(...)
All right, I think we're good though. I think we've got pretty much the main massive tests running. And I have confidence now that more or less our view is functioning, which we didn't even have tests for this view previously.
(...)
Yeah, it's been a pretty good day, a long one. And it's a cold one too, we're at minus 20, minus like 21. I think it got down to today, Celsius.
(...)
Man,(...) what is that in Fahrenheit?
(...)
Minus five, minus six, doesn't sound so bad.
(...)
That's cold, yeah.
(...)
Painfully cold, my face turns numb. I basically had to force myself to go for a walk even to get out of the house.
(...)
And my face was like red, beat red, my return. But yeah,(...) walking across town is a painful endeavor.
(...)
But yeah, it's important to still be active. I'll probably go for one more walk this evening just because, and then I'll go to bed.
(...)
Yeah, true that.(...) And I learned my first year here in Finland, it's, well, bearskin is a good one. And I think because it's sort of like insulating layer,
(...)
I thought I could just get a really big coat and I would be fine, but it turned out you need layers. You gotta have a few, like a long underwear layer, going all the way down. And then like a sweater and then my winter coat. And sometimes I even need like two sweaters, but just having these like layers with insulated,
(...)
it works much better than just if I had a big coat that was all sealed up and a scarf so your heat doesn't.
(...)
That's my basic survival tips.
(...)
Yeah, that's right. I have to keep it trapped there.
(...)
Yeah, a friend told me that my first year here, that was like one of the key survival tips for the winter. Although the winters have been really mild until this winter has been like one of the coldest ones
(...)
in the 10 years that I've been here.
(...)
The other one is the summer because the sun doesn't set. So there's a whole different survival strategy there to like get your sleep in,(...) darkening curtains.
(...)
Oh,(...) wow, I think we powered through it. I'm getting like super tired, but I think our tests should reflect
(...)
what I see as the admin user.
(...)
And if I create a dummy user or a fake user that only gets assigned to one house.
(...)
And then, for example, I add them to one home.
(...)
And I can't remember if home zero
(...)
was in a group or not.
(...)
It's not, it's not in a group.
(...)
Home one is, so then I'll add them to home one as well.
(...)
(clicking)
(...)
And I'll go incognito.
(...)
And I'll go to the home screen. And I think this is actually something I need to test. Oof. Ah, yes.
(...)
So that's a bug.(...) Dang it.(...) Thought I could get ready to go to bed, but no.
(...)
I need to check if the user is logged in. Just return the context there. Return early, early return.
(...)
Nice.
(...)
(soft music)
(...)
Just thinking if I need a test case for that.
(...)
Then if I go to homes,(...) home zero and home one. Yeah,(...) it works as expected.
(...)
(soft music)
(...)
Super cool, yeah. All right, well I better call it good. I'll try to stream a bit earlier tomorrow. Probably not this late.
(...)
But yeah, tomorrow and Saturday. I'll have some time for streaming and continuing this Jerry Life project. So it's been cool.
(...)
Glad you got to, glad you stopped in Rebel. I appreciate it and glad we got to chat for a little bit.(...) Yeah, I hope we get to hang out another time soon. And I'm gonna work on some kind of stream points and if you got some ideas on how people, how the participants could use their stream points such as like doing pair programming(...) or having me review a poll request of theirs or something like that. I'm open to some ideas, even just like hydration, exercise points, stuff like that.
(...)
It was suggested today that I look into how people can use these stream points. I hadn't even really thought of it, but yeah, to make it more engaging and rewarding for the viewer.
(...)
All right, well have a good day. I hope you're doing well and see you around.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment