I had scribbled this blog last year. Somehow I forgot to publish. During this quarantine time with lot of retrospection, I knew what I was missing.
Emphasizing On Writing Tests
I am big fan of tests. Tests not only test your code but also tell others how your code works. (Disclaimer: Provided enough tests)
There is the famous TDD in agile. Writing failing tests before writing the code, which gives lot of clarity for implementation. It gives you confidence. Then there is BDD which let’s tech and non-tech users to write tests using common framework. “Given-when-then” formula is most common for BDD.Writing tests gives you confidence. You should write units tests, integration tests, test with mocks and all other useful tests.
Tests helps in code reviews, tests help in refactoring code. Tests helps to speed up new dependent features. Stable code base must have tests (IMHO). As architecture evolves we need to find ways on how we can improve writing tests. Tests for UI, tests for micro-services, monitoring tests, snapshot tests, selenium tests.
There are tons of service which provide you the way to expose your localhost on internet. We need it for testing 3rd party APIs or show casing current development server. For example the most popular ones are:
Setup the listening port using nginx on the server associating it with the subdomain.
Add subdomain in DNS(We will be using awesome Digital Ocean DNS)
Add SSL certificate provided by our favorite Let’s Encrypt
Forward the traffic using amazing SSH command.
Step 1 - Configuring server with nginx to serve traffic for the subdomain
Please install nginx on the server first.
You need to add one config file for nginx in sites-available folder of /etc/nginx assuming you are using Ubutnu. The nginx config file looks like below.
There is server_name directive which tell what domain to serve the request, listen directive for which port to listen on the domain.
The location directive is important here, here we are just proxing request from localhost with port 4242. This port is important since we will be directing our localhost traffic to it. Then there is setting header on the request.
Rest of directive is enabling websocket support on this setup by upgrading the connection. That’s all.
Note: You need to change server_name as per your required sub-domain instead of 42.igauravsehrawat.com.
Step 2 - Configuring Subdomain on DNS
Using Digital Ocean DNS Service, we will add a subdomain of our choice, it be 42.igauravsehrawat.com as done in step 1
For adding a subdomain, we will create 3 records(A Record, AAAA record, CNAME record)
A and AAAA records will redirect to our digital ocean server as shown below.
CNAME is just an alias of our A/AAAA record. All three will appear as shown below
So that’s all here, you should be able to access your sub-domain over internet, showing you 502 Bad Gateway page, which is expected since nothing is being forwarded to port 4242.
Step 3 - Enabling SSL
Enabling SSL is piece of cake, more easy than that.Follow the certbot installation sets from here
Then run the magic command for nginx
sudo certbot --nginx
You will see something like below
Run it twice, one for sub-domain and one for CNAME(alias).
Now you should see this we you go to your sub-domain www.42.igauravsehrawat.com
This is expected since nothing is running on port 4242 of localhost at the server.
Woof, we are just one step away from the happy dance.
-N tells “Do not execute a remote command. This is useful for just forwarding ports.”
-R tells “Connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.”
First localhost is of the server and second is of local machine, then the address of your server. If you set up the SSH keys(Recommended) it would be seamless, no password, nothing.
That’s it.
Happy Dance as promised.
Wait, wait, we haven’t tested yet.
Testing
For testing I will just create a react app using create-react-app and do npm start to run it on port 3000(default).
And then run the magic SSH command
ssh -N -R localhost:4242:localhost:3000 root@42.igauravsehrawat.com
See it in action
Conclusion
With power of just one server, it is not that hard to have your own setup. You just have your own customized, SSL enable sub domain with no restrictions.
This puzzle is from my mentor and I like how it is very pragmatic and not just a brain-teaser. So the official language of the puzzle is as below
Matter of Life or Death
An evil wizard imprisoned 64
mathematicians. The wizard announces: “Tomorrow I will have you all
stand in a line, one behind the other, and put a hat on each of your
heads. The hat will be either black or white. You can see the hats of
everyone in front of you but you can’t see your own and you can’t turn
behind. Starting from the last person in the line, I will ask the color of
the hat that is on your head. You are allowed to say aloud single word
answer: “white” or “black”. If you get it right, you will be released. Else
you will be shot dead”. The geeks have a night to discuss their strategy.
What strategy should the geeks develop so that largest number of them can survive!
Some clarifications:
One don’t know what happened to previous person, all you can do is see in-front of you and “hear the response of all other people”.
You can’t see the shadow of person behind you.
Any other social hack, you might think of.
Let’s focus on the question again.
What strategy should the geeks develop so that largest number of them can survive!
The obvious possibility of surviving is 50% without doubt, how??. Well a group of 2 can save one of the person for sure i.e one person from the group has to tell right color to other person.
We have signal other people, what’s better than unity and forming a group? So we group people and try to signal more than one people at once.
Another hint:
Black and white! Two variables, can do anything with bits, binary?
2 people signal group
A group of two people can signal 4 four people using 2 bits. 00, 01, 10, 11.
So they can signal if all people’s hat have same color using 00
They can count no. of color of either pre-decided color, let’s white is the color.
If the signal is black-black i.e 00, it means everyone is white so the all four people will say white.
If the signal is white-black i.e 10, it means the first person can count no of white and black infront of him, if there are 2 white hats then he will say black, if there is one white hat in front of him, he way say white.
Next person will account the choice of previous and do the calculation similarly.
Whoaa! never thought of it before, thought whatever is in destiny will happen. LOL.
So out of 64, 6 people can form the signal group and can give 64 kinds of signals i.e counting/numbers.
6 people signal group
Can save at-least 58 people.
So now that’s a life saving puzzle, should put enough interest to solve more puzzles.
Humor
There are 10 types of people in the world, one who understands binary and the rest who doesn’t.
If it doesn’t work, you know that it is confused and won’t give an error. This confusion could have been solved by giving error/warning but CSS choose not too. That’s why all this hate for CSS on internet.
Let’s come to drawing a horizontal tree with a root in center, because WHY not. The tree structure should be like
A node can have multiple children, in simple terms and each tree will be centered around root. Don’t bother about responsive-ness for now, it will require some javascript and SVG which we aren’t going to do for now.
Concept(s) needed
CSS pseudo elements
What is a pseudo element?
You might have used pseudo classes abundantly, pseudo elements are similar to pseudo classes but they are used to style specific part of the selected item. For eg. :before/::before, :after/::after, :placeholder, :grammar-error etc.
That’s it, all we need is pseudo elements(as the heading states) to make the branches out of the nodes, either horizontal or vertical. Also knowledge of relative positioning and absolute positioning will come handy.
We will make this tree in parts, right part has root included itself. First lets draw the tree in crude way.
So we have branches, which have entry and entry can other branches and entries as its child(ren). Let’s first understand how CSS will be applied, CSS will be applied from inner most tag to other most tag, so the height of branches will add up and each branch’s height will be cumulative from previous height.
We have fixed the node’s width to 150 px here also incoming connection and outgoing connection are 50 px each, therefore a branch will be 250 px wide.
Let’s come to drawing connections, we have entry as node which is our reference for connections, we will create incoming connection on the right tree using :after pseudo element. For branch’s height we will use :before pseudo element on entry element. It’s possible to swap :before and :after but need to some alignment.
Branch has the outgoing connection.
Think pseudo elements as box and then choose their side, that’s what we have done, for incoming connection we chose border-top, for branch height we chose border-left. See the image how boxes looks like.
Notice how positioning is done using top and left.
Notice the top and margin-top to make this label centered in the div using position absolute.
Whew, that’s all.
The left sub tree is easy and left as an exercise to the reader.(Just kidding.)
Left sub tree
For the left part construct the tree same as right tree but some CSS needs to be reversed. The quickest way to understand this is see the diff of two tree’s CSS
Now if you notice branch is place with margin of 250 px from right in its position, the magenta color connection is placed at 100 px to right from nodes which is opposite of what is on right side tree. .entry-inverse is now positioned with respect to right and .label-inverse is also position with respect to right.
CSS polishing
Now comes the task of providing finish to the product, we want round curves instead of bland straight lines in the tree. It’s important to note on :first-child and :last-child need to have rounded corners. Like the pic given below.
For this we have provided round border to straight line and incoming connection to the node for their :first-child and :last-child with :before and :after property individually. Also we will truncate the height to 50% and position it 50% from top.
If now you remove the dashed lines, you will get the straight lines except for the sole children, for that we don’t want round corner and not want to display straight line. So the below CSS will help that.
So first technical blog of the year. It’s simple blog as it seems from the title. UX is important here too, that will also be the focus apart from code. This blog is from a task given to me by my mentor.
So let’s see the flow.
We want to have two lists and item can be added and deleted in each list.
An item can also be moved to other list by dragging it over to other list’s place.
We want to create a placeholder where the item is going to be placed.
We want to slightly tilt the item being dragged to show distinction.
So we need to know drag and drop API’s from MDN(a good documentation place). There are multiple API’s but we just need 4 of those. Those 4 are ondrag, ‘ondragover’, ‘ondragleave’, ‘ondragend’. We don’t need ondrop since we are using placeholder to mark the position to place the elements.
So let’s define the behavior.
What happens when your start dragging?
Visual clue from rest of items present there(like tilted).
How to show the place when an item is going to be dropped.
Show a visual clue like placeholder.
What happens if drag fails(i.e it goes out of browser)?
It should come to the last visual clue it is supposed to come.
The above ones are 2 helper functions for removing and inserting placeholder as the name suggests. Also you will notice there is event.preventDefault used because some OS browsers have other behaviors for dragging an object. So we will avoid that.
listItemDragStartHandler (funny name) is an ondrag method, here we want to save the dragged item in global var source and height & width of dragged element for placeholder. Then we attach a custom image for dragging which is bit tilted to show some relevance which is also stored in a global var dragImageSource.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
functionlistItemDragStartHandler(event){source=event.currentTarget;heightWidth=[];heightWidth.push(source.offsetHeight);heightWidth.push(source.offsetWidth);event.dataTransfer.setData('text/html',event.currentTarget.innerHTML);event.dataTransfer.effectAllowed='move';// Drag image logicdragImageSource=source.cloneNode(true);dragImageSource.style.position='absolute';// Don't show the elementdragImageSource.style.top='0px';dragImageSource.style.left='-'+String(window.innerWidth)+'px';// dragImageSource.style.left = '-100px';vartoTiltElement=dragImageSource.getElementsByClassName('item-list-element')[0];toTiltElement.style.transform='rotate(5deg)';document.body.append(dragImageSource);event.dataTransfer.setDragImage(dragImageSource,heightWidth[1]/2,heightWidth[0]/2);}
We have ondragover and ondragleave methods below which basically insert placeholder according to latest movement. In dragoverHandler we hide the existing item from it’s original place and check if we are dragging over a new element using lastDragOverElementId, only then we remove existing placeholder and insert new placeholder.
In dragLeaveHandler, this is specifically needed to have a placeholder at the end of the list because we are always appending above existing drag over element. But when element exit the list it’s place should be at end. So here we check if it has left the last visible element(remember we still have one hidden original element in the list).
Also you will notice we have a timeout here for disabling ondragleave for few moments, this is for stop a chain reaction between ondragover and ondragleave since a list element passes through the dragged element when placing the placeholder. Then at-last we set lastDragOverElementId to null since a new dragged element will hover over other element now or re-enter.
functiondragLeaveHandler(event){event.preventDefault();varcurrentElement=event.currentTarget;varlistContainer=currentElement.parentNode;varelementList=listContainer.getElementsByClassName('item-template-container');varvisibleElementList=[];vari=0;for(i=0;i<elementList.length;i++){if(elementList[i].style.display!=='none'){visibleElementList.push(elementList[i]);}}// Last element ondragleave handler should be delayed, otherwise it// would spin off chain reaction.varlastVisibleElement=visibleElementList[visibleElementList.length-1];// Basically last elementif(currentElement.id===lastVisibleElement.getAttribute('id')){lastVisibleElement.removeAttribute('ondragleave');removePlaceholder();insertPlaceholder(currentElement,'leave');// This delayed the chain reactionsetTimeout(function(){visibleElementList[visibleElementList.length-1].setAttribute('ondragleave','dragLeaveHandler(event);');},500);// When event is on last element set the lastDragOverElementId to null// then dragover to lastVisibleElement(second last element) can be handled// otherwise dragover to second last element won't show placeholder.lastDragOverElementId=null;}}
This handler is needed to place the dragged element to placeholder place irrespective of drop, so drop is mouse release operation here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
functiondragEndHandler(event){event.preventDefault();// Check the dropEffectdragImageSource.remove();varlistElement=document.getElementById('grayed-empty-node')varlistContainer=listElement.parentNode;if(event.dataTransfer.dropEffect==='none'||event.dataTransfer.dropEffect==='move'){vargrayEmptyNode=document.getElementById('grayed-empty-node');// When grayEmptyNode is null, that will append at the end.listContainer.insertBefore(source,grayEmptyNode);source.style.display='';removePlaceholder();}}
Ahoy!! I can’t understand without a demo. I have a demo here. There are few things I haven’t mentioned like fading of placeholder and using livereload while developing this.