Mantilogs Mk II - Part 5: More tests (Whoopee :|) and on to the UI

Mantilogs Mk II - Part 5: More tests (Whoopee :|) and on to the UI

So, now that I have figure out how the token auth works in Django Rest Framework (though it's implementation isn't great, I will probably change it at some point but it suits my purposes for development anyway...) I can get to finishing writing the endpoint tests.

Once that's done I suppose I'll be starting on the UI if I recall? I should have wrote it on the whiteboard. Writing the UI will probably require a few more endpoints and serializers. I'll try to cover the ones I expect I will need first, though more may crop up as I go.

Anyway, for now, tests.

That'll do.

Originally I was going to write tests for all of the CRUD operations but I realized those are handled by DRF and I wouldn't be testing my own code in doing so. I just made sure I could create and read each of them. This might be a mistake I pay for later but I figure it should be alright.

Next step is to write some serializers that can look up each of the logs by gecko ID. This will probably require some custom router and viewset code on top of the serializer so... this should be interesting with how things have been going with the documentation so far.

This looks promising.

Or maybe this.

I'll try the action first, then the URL-based filtering.

Yeah, I am not sure exactly how to use an action to work with another serializer. Tried a few things and didn't seem to be getting anywhere. It's 11am so I will opt for the more straight-forward approach that may take a little more work.

Yep. That's got it.

It's verking!

Now to do the same for every log and also add the /api/leo bit to the front of the urls to keep things uniform.

re_path('^api/leo/feed_logs_list/(?P<gecko>.+)/$', GeckoFeedLogList.as_view()),
    re_path('^api/leo/defecation_logs_list/(?P<gecko>.+)/$', GeckoDefecationLogList.as_view()),
    re_path('^api/leo/interaction_logs_list/(?P<gecko>.+)/$', GeckoInteractionLogList.as_view()),
    re_path('^api/leo/incident_logs_list/(?P<gecko>.+)/$', GeckoIncidentLogList.as_view()),
    re_path('^api/leo/enrichment_logs_list/(?P<gecko>.+)/$', GeckoEnrichmentLogList().as_view()),
URLs

class GeckoFeedLogList(generics.ListAPIView):
    serializer_class = FeedLogSerializer
    def get_queryset(self):
        """
        Return all feed logs associated with gecko ID.
        """
        gecko_id = self.kwargs['gecko']
        return Feed_Log.objects.filter(gecko=gecko_id)

class GeckoDefecationLogList(generics.ListAPIView):
    serializer_class = DefecationLogSerializer
    def get_queryset(self):
        gecko_id = self.kwargs['gecko']
        return Defecation_Log.objects.filter(gecko=gecko_id)

class GeckoInteractionLogList(generics.ListAPIView):
    serializer_class = InteractionLogSerializer
    def get_queryset(self):
        gecko_id = self.kwargs['gecko']
        return Interaction_Log.objects.filter(gecko=gecko_id)

class GeckoIncidentLogList(generics.ListAPIView):
    serializer_class = IncidentLogSerializer
    def get_queryset(self):
        gecko_id = self.kwargs['gecko']
        return Incident_Log.objects.filter(gecko=gecko_id)

class GeckoEnrichmentLogList(generics.ListAPIView):
    serializer_class = EnrichmentLogSerializer
    def get_queryset(self):
        gecko_id = self.kwargs['gecko']
        return Enrichment_Log.objects.filter(gecko=gecko_id)
Views

With that I have to write some more tests to be sure these all work as intended testing if a log is added in the test DB there is one log on the crash test gecko.

# Test filtered list
        response = client.get('/api/leo/enrichment_logs_list/'+str(self.crash_test_gecko.id)+'/')
        self.assertEqual(len(response.data), 1)

All tests pass, looks like it's time to start the UI design. Now I have some more decisions to make.

I'd prefer to use a stateful frontend here but I have a distaste for large, bloated, dependency-heavy libraries so I would prefer to avoid React. This front-end could be built in Godot if I wanted to, but it's probably best to stick to javascript for the moment.

I guess I can do a little googling, might find something I like.

I should also consider my CSS frameworks, I could stick with Bulma or try something new.

As far as front-ends go I am leaning toward mithril.js but I will keep looking for the moment.

I also found Preact, which is seemingly react with the bloat removed.

All I need is a stateful single page application for this UI. It needs to be able to keep the auth token stored and handle updating it.

You know... in messing around with Mithril I am reminded of why I try to avoid javascript.

 var root = document.body;


        console.log("What the deuce?");
        var gecko_data = {};
        var fetch_gecko = function() {
            m.request({
                method: "GET",
                url: "http://127.0.0.1:8000/leopard_gecko/api/leo/geckos/",
            })
            .then(function(data) {
                console.log(data);
                gecko_data = data;
                m.mount(root, {
                    view: function() {
                        return m("p", gecko_data[0]['name']);
                    }
                });
            });
        };
        fetch_gecko();

So ugly...

Maybe I should just suck it up and use React, break everything into components. Right now I am even considering just building it in Godot and compiling a web version from that.

Not talking shit about Mithril.js, just not sure it's the best choice for this application. I really admire it's simplicity and how straightforward it is.

Hmm...

What to do, what to do?

I could just use the industry standard and go with React, which I have at least minimal experience with... though I dislike it.

I could use Godot and compile a phone version, browser version, linux version and windows version(screw you, mac.).

I could build my own stateful API client from scratch in vanilla JS, though that would likely take the most time.

I could give Preact a shot, see how that goes.

Part of me is really leaning toward Godot, though I am not so sure that's the best way to handle this. Compiling for mobile would be interesting...

The other part is leaning toward Preact. Traditionally I use web-based UIs for these things.

I know I would have more fun developing it with Godot since I can avoid the devil known as JavaScript. I don't hate JavaScript but it has gotten really annoying to use these days. Everyone expects you to know frameworks rather than the actual language itself. A lot of the things people use libraries for nowadays are covered in vanilla JS and it just shows how library dependant the ecosystem has become.

Personally I prefer being able to write something my own way from scratch if possible. I use frameworks and libraries whenever I feel like there's a time constraint, which is a lot of the time nowadays but I would really rather just sit down and set about designing and developing everything from the ground up with nothing but the built in libraries in a particular language.

Anyway, I think I will write a little test in Godot and set up a Preact project as well. If the Godot idea falls through I can bang something together in JS and that'll be fine. With Godot I will have more access to the hardware and can say, make a phone buzz to remind of feeding time for instance. I could also set up push notifications through Mantilogs backend but in my experience those have been hit or miss, most of the time I don't get push notifications from web services.

Yeah, Godot. What the hell, why not?

Another reason I hate the dependency hell of JS:

Neat.

Well, got a Preact project ready to if I need it. I'll do some prototyping in both and make my decision after that. To be honest I would prefer to build all my UIs in Godot these days but can't be sure if it's feasible.

Anyway... Godot first.

Yep, definately prefer designing UI like this.

Bashed together UI.

I have to build a theme and all that, but for now I will focus on function. Actually, looking at this I don't think I need the labels.

There. A simple login screen.

I can worry about margins and all that later, need some functionality now.

A chilled out groove.

So, function. Basically I need to make rest api requests from godot. Done it before, should not be too hard.

Oh, I see they have changed a lot of things in GDScript for Godot 4. Gonna take a bit of getting used to.

We have login.

The API returns a token.

Now I just have to add that token to the header when I send my requests and I should be authenticated. The rest is just repeating what I already did here and parsing JSON into the UI. This should be pretty simple from here.

Next I guess I will handle the token and GETting the gecko index. Pulling the profile picture and displaying it will be an interesting challenge, I can get the data but forcing it to fit in the UI without looking wonky will be tricky.

So far I am liking how this is going.

Logging in and retrieving data.

I got data from the gecko index, so far so good. I'll need to create a scene for holding the gecko data and append them to the UI as they are processed. I am actually having fun with this project again.

Size is apparently going to be an issue.

The data is there, now I just need to... fix how it is displayed.

Unfortunately that's all the time I have for today, gotta clock out and make some dinner. I'll pick back up here in the morning.