[Angular JS] Setting a combobox based on selection of another one

This might be my first post which touch Angular JS, and wanted to let you guys know that I too joined the backend to frontend club! Currently Angular JS is powering https://browserperfdash.igalia.com/ with Django REST at the backend – and I think its super fast, easy to develop and allows for a cleam responsive UI – WOW is the word.

Problem
You have a data model, which looks something like:

bots = [{ 'bot1' : {'platform': "Linux", id:1}}, { 'bot2' : {'platform': "Windows", id:2}}];
platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     

You have a select box bots and another select box Platforms and you need the following logic to happen:

  1. When no bot is selected,the Platforms combo should show All all the platform options
  2. When a bot is selected, it should force the Platform combo to show the platform property of bot selected, and should disable them to make no further changes.

Solution
You will need the following Angular script to make this work. Add this to your scripts.js or wherever place and include it in your html file.

app.controller('AppController', function($scope) {
    $scope.bots = [{ 'name': 'bot1', 'platform': "Linux", id:1}, { 'name': 'bot2', 'platform': "Windows", id:2}];
    $scope.platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     
});

see that you can even add this directly to the html file with the tag. Now you can add the following to the HTML file so that the data gets correctly rendered to the browser.

<div class="form-group">
  <label for="bot">Bot</label>
  <select name="bot" class="form-control" ng-model="selectedBot"
	  ng-options="bot.name for bot in bots">
      <option value="">--All bots--</option>
  </select>
</div>
<div class="form-group">
  <label for="platform">Platform</label>
  <select name="platform" class="form-control" ng-model="selectedPlatform" ng-disabled="selectedBot">
      <option value="">--All platforms--</option>
      <option ng-repeat="x in platforms" value="{{ x.name }}">{{ x.name }}</option>
      <option value="{{ selectedBot.platform }}" ng-selected="selectedBot" ng-show="selectedBot">
	  {{ selectedBot.platform }}</option>
  </select>
</div>

How it works?

  • The {{ x.name }} makes sure that all the platforms are shown initially making sure our condition (1) above.
  • The {{ selectedBot.platform }} makes sure that when the bot select is clicked, this option value is set for the combo box – adding to (2) above.
  • The ng-selected="selectedBot" ng-show="selectedBot" makes sure that the combo gets disabled when someone selects in some value for bots contributing to (2) above
  • You can see the dropdowns live in action at https://browserperfdash.igalia.com/ and do take a look and comment if something seems weird.

    Update: It seems like there was a problem with this approach as the selectedPlatform is not getting set correctly, even though the combo gets set. You can fix this by
    adding in the following action on ng-change on the select combo

    <select name="bot" class="form-control" ng-model="selectedBot"
          ng-options="bot.name for bot in bots" ng-change="updateOtherCombos()">
      <option value="">--All bots--</option>
    </select>
    

    and now defining the function updateOtherCombos() to your controllers.js

    app.controller('AppController', function($scope) {
        $scope.bots = [{ 'name': 'bot1', 'platform': "Linux", id:1}, { 'name': 'bot2', 'platform': "Windows", id:2}];
        $scope.platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     
        $scope.updateOtherCombos = function () {
          if ( $scope.selectedBot ) {
    	  $scope.selectedPlatform = $scope.selectedBot.platform;
    	  $scope.selectedCPU = $scope.selectedBot.cpu;
    	  $scope.selectedGPU = $scope.selectedBot.gpu;
          }
       };
    });
    

API custom authentication with django-rest-framework

Long time since I blogged about anything in here! This time I am working on building a python-django powered dashboard for browser test result analysis with Igalia, and came across this the frist day! Let me get into this straight, following my usual template of blog posts

Scenario
You have a default User login model, but have some bot POSTing at say yourwebsite/bot-api. Your bot has its own authentication details sent as parameters in the POST as

{bot_name: fooboot, password: bar}

and you want to authenticate this from a Bot model in your django application, and make sure that this thing go throgh only after a green flag.

Solution
The best method here is to write a custom authentication in your views.py which would look like

from rest_framework import authentication
from your_models import Bot 

class BotAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        bot_name = request.POST.get('bot_name')
        bot_password = request.POST.get('password')

        if not bot_name or not bot_password:
            return None

        try:
            bot = Bot.objects.get(name=bot_name)
        
        # If you have some other methods to auth, use here
        if bot.password != bot_password:
                return None
        except Bot.DoesNotExist:
            raise exceptions.AuthenticationFailed('The bot failed to authenticate')

        return (bot, None)

and you can directly use this in your ApiView which should be ran on recieving a hit on the API.

from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework import authentication, permissions

class BotReportView(APIView):
    authentication_classes = (BotAuthentication,)
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def post(self, request, format=None):
         return HttpResponse("If it reached here, the bot was authenticated = yay")

Well. There are issues with using such a plain-text authentication, and doing a 1:1 password comparison. In real world, you might want to use django password field and authentication functions to compute hash of the recieved password, and compare with the one in the database table.

Hope this helps!

[git] Reverting an accidental commit/amend using reset

Alright. So this one might sound a special case, but there are chances that something like this scenario might turn up too, while playing with git.

Scenario:

You are working on top of a commit de7504f : My original commit, made some changes, and you really wanted to make it into a new commit, but accidently you gave git commit --amend and you are now in the edit commit message of de7504f.

Once saved, you can see in git log that you are in a new commit-id: 7645040: My original commit and amended change.

This can be equivalent to typing git commit, typing in the commit message, saving it – and later thinking – “God, I shouldn’t’ve committed it”.

Solution:

The idea is to run git reset and it would just take you back to a point where you have the changes staged, but not committed yet. To be more human, this is the place after you have made your changes, and typed in git add too.

You can get the commit-id straight from git log, but for my above scenario, since it was an amend, it might not just work. For that, we got git reflog

git reflog

it would list out commit id of every single change you did including amend, rebase, chgeckout, reset etc.

7645040 HEAD@{0}: commit (amend): My original commit and amended change
de7504f HEAD@{1}: commit: My original commit

Yay! Now you need to just run

git reset 7645040 
git status

and you are back in history where you have git add -ed the files, but not done git commit --amend yet. You can add those to a separate commit, or stash it or do whatever.

If you pass git reset 7645040 --hard, all changes which you did after 7645040 would be just thrown off, so use it with caution.

References: https://git-scm.com/docs/git-reset

Rewriting Git history, correcting a previous commit in your PR

This blog post should be dedicated to my mentor jaragunde at Igalia, as he had been the one pointing me out to go back again and again to that wrong PR, I made, and correct it. The first time I did, it sounded a bit confusing, and here you go!

Scenario:
You are working on an XYZ Pull Request having a series of commits namely 234234, 11233 and the latest one being 5514134. Your mentor tells you there is a mistake in 11233, and you want to go back to that commit, and correct the same.

Alright, so lets assume you are in the branch myfaultybranch with the git log showing up 5514134 at the top.

Steps:

  1. git stash – lets make sure there are no debris left!
  2. git rebase -i 11233^ – make sure you put the ^ at the end, otherwise the following steps would fail miserably.
  3. on the screen that come up, you will have the other commits too listed, looking like
    pick 11233 [#222] Your faulty commit message here
    pick 234234 [#222] This commit has no problem
    

    Edit the first line, from pick to edit so that it looks like:

    edit 11233 [#222] Your faulty commit message here
    pick 234234 [#222] This commit has no problem
    
  4. Save, and you are in a state where you are one step before committing 11233. Yay! Now make all your changes you want, correct all the mistakes at your ease!
  5. Once set, git add and git commit --amend and modify the commit message too, if you want
  6. All set, and you can now execute git rebase --continue and you will be back in your commit 5514134. Yay!
  7. Push your changes to your origin via a git push -f myfaultybranch
  8. In case you screw up in between, please do git reset --hard 5514134 and you will be reverted back 🙂

Hope it helps! Lets rewrite history! Found something wrong ? Please do comment!