Saturday, December 2, 2017

Dealing with global web assets on Django

Dealing with global web assets on Django, my thoughts.

Working with Django, often your default mode of thought is apps. App are like these small self-contain programs that have their own urls, views, templates and the web assets that come with templates. Web assets, I mean those css (or Sass or Less files), images and maybe some JavaScript.

But when you start thinking long term, as far as templates go, apps will prove unmanageable. You'll start thinking of breaking then into smaller reusable units while leveraging template inheritance. Which leads us to the dilemma, how do we handle the global web assets?

My first idea was just put it on the /static folder. It works but not a good idea because a standard django .gitignore will exclude the /static folder.  Another thing, /static folder is where the django-admin collectstatic command puts all files it gets from the your dependency modules. It's not uncommon to have hundreds of MB inside this folder - hence, you don't commit them into repos.

So, I had to figure out a way that allowed to me get around the .gitignore rule (which I won't edit - they are standard for a reason) with the assets. What I ended up with is

1. Putting the global, shared web assets in an /assets folder
2. Inside the /assets folder are subfolders for css, js, img, font
3. Change my django configuration to handle it.

STATIC_ROOT = str(ROOT_DIR('static'))

    ('projectA1', str(ROOT_DIR('assets'))),


The ROOT_DIR function is just a helper function that prints out the path to static relative to the root directory.

So anyway, an example usage then is like .. href="{% static "projectA1/css/style.css" %}" which is pretty nice. Details are here.

Monday, November 6, 2017

Git aware prompts for Windows just like in Bash

At work, I use a bash terminal. It's git aware so it looks like this:

My bash prmpt

It shows the current branch and color codes the status of the repo among other things. If you want the settings, you can get the gist for it.

At home, I work with Windows. I know I can get a bash shell running on Windows but I wondered if there's a same thing for the Windows terminal.

The first thing I learn is that Windows has two terminals, the ordinary cmd.exe thing and a much more powerful thing called Powershell. Powershell can do what cmd can do and much more. Powershell is more of a platform rather than just a window to issue commands.

Which then lead me to posh-git. At default settings, it just changes your prompt to be git-aware. For example:

C:\Users\jaypax\projects\posh-git [master+0 ~1 -0 !]>

It's not exactly like my bash prompt but it's close. I might be even convinced it's better with a little tweaking.

I got to say it's pretty nice but don't take my word for it. Take it for a spin.

Monday, October 16, 2017

Doing listviews with empty lists and pullrefresh in Nativescript-ng

This was a pain in the butt to do right and I had to do a "bit" of trial and error to get this right.

All I wanted do was show a "centered" bold, large text on the screen when a list is empty and the actual list view when there's data on the list with both having support for pull to refresh action.

Googling this well probably lead you to Telerik's doc on the RadListView for pullToRefresh which I call shenanigans on because I couldn't make it to work. So we move to next idea which is Brad Martin's pullToRefresh nativescript plugin.

I did get Martin's nativescript plugin to work on my first attempt sans a bug that was a bit odd. I'm not even sure if the bug can be replicated on another machine. Anyhow, my first attempt's code looked like this:

 <PullToRefresh (refresh)="refreshList($event)" row="1">  
     <GridLayout horizontalAlignment="center" verticalAlignment="center"   
           rows="*" columns="*" *ngIf="emptyList()">  
       <Label horizontalAlignment="center" verticalAlignment="center" row="1" column="1" class="h2"   
           text="No Orders Available."></Label>  
     <ListView [items]="ordersList"   
          (itemTap)="onOrderTap($event)" class="list-group">  
       <ng-template let-order="item" let-odd="odd" let-even="even">  
         <GridLayout [class.odd]="odd" [class.even]="even" columns="auto, *" rows="auto">  
           <Label col="0" class="iconbkg" text=""></Label>  
           <avatar [avatardata]="order.avatar_prop"></avatar>  
           <StackLayout col="1" class="formMessage">  
             <GridLayout columns="auto, 100, *" rows="auto">  
               <Label class="h3 text-left" col="0" [text]="'Order #' + order.number"></Label>  
               <Label class="h3 text-right" col="1" [text]="order.date_placed | date:'MMMM dd yyyy'"></Label>  
             <Label class="body" [text]="'City: ' + order.shipping_address.line4 + ', ' + order.shipping_address.state"></Label>  
             <Label class="body" [text]="order.lines.length + ' Item(s)'"></Label>  

If you refer to the inner Gridlayout with the *ngIf element. The idea was to show this gridLayout when the list is empty. Don't bother with the ListView component because it will not show anything if [items] is empty.

The problem was when I do a pull to refresh, it was causing a crash in the android emulator saying that it was referencing a null view of some sort.

I eventually got it to do want I wanted. I did two things:

1. Move the empty list gridLayout into its own pullToRefresh container. Like so:

<PullToRefresh (refresh)="refreshList($event)" row="1" col="1" *ngIf="emptyList()">  
     <GridLayout horizontalAlignment="center" verticalAlignment="center" rows="*" columns="*">  
       <Label horizontalAlignment="center" verticalAlignment="center" row="1" column="1" class="h2"   
           text="No Orders Available."></Label>  

   <PullToRefresh (refresh)="refreshList($event)" row="1">  
     <ListView [items]="ordersList"   
          (itemTap)="onOrderTap($event)" class="list-group">

2. I removed the ChangeDetectionStrategy in the @component declaration of the view class.

 With these two changes, the error no longer happened and it works perfectly.