Americans don't punish children for the acts of their parents.

Originally Posted on Facebook 6/20/2018.  It still applies today.

As someone who identifies as libertarian... is often accused of being republican (I'm not) and is a little more conservative on crime then he cares to admit let me just say:

Americans don't punish children for the acts of their parents.

Whether the parents are earnest in their asylum claims or not. Whether the parents crossed the boarder legally or illegally:

Americans don't punish children for the acts of their parents.

When parents commit crimes, we don't send the children to prison. When parents die in debt we don't pass that debt to the children. Because again:

Americans don't punish children for the acts of their parents.

    Posted: Jun 20, 2019

Resetting the Initial NID to 1 After Deleting All Nodes in Drupal 8

 

Writing this mostly as a note to myself.

I'm in the process of migrating nodes from three different Drupal sites into a new Drupal 8 site.  Over the last day or so, I've been working on building out the Migration YML (Migration API FTW).  Of course as I've been debugging I've been importing and rolling back migrations.  Of course, as I do this, my starting NID is getting larger and larger.  It was over after me test data nigrations.  When the time comes for the final import of content, I want the first NID to be 1 (just for cleanliness sake).

In Drupal 7 the delete all module did this with a "--reset" flag but doesn't in D8.  Here's the couple of lines of SQL code to reset the auto increment on the necessary tables:

  1. ALTER TABLE `node_revision` AUTO_INCREMENT=1;
  2. ALTER TABLE `node_field_data` AUTO_INCREMENT=1;
  3. ALTER TABLE `node_field_revision` AUTO_INCREMENT=1;

Make sure you DELETE all nodes before doing this, otherwise you are likely to cause data corruption down the line,

Share and Enjoy!

    Posted: May 2, 2019

Building a Masonry Grid View with Bootstrap in Drupal 8

 

I’m in the process of moving my photography site into my current Drupal 8 site.  After a little thought I decided that I wanted to have my photos in a grid using a masonry layout (you know, the layout made famous by Pinterest).   The image attached to this article gives a quick demonstration.   On many sites this is accomplished using David DeSandro’s masonry.js.  

Drupal has a Masonry Api and a companion Masonry Views Module.  I installed the modules and they mostly worked but didn't quite meet my needs.  I wanted a little more control of the grid.  I wanted to have a responsive design with different number of columns based on screen size (1 or 2 columns on phones, 3 columns on tablets, 4 on large desktops).  Although my current design doesn't require it, I suspect  that down the road I might want certain images to span multiple columns.  I use bootstrap on my sites to make things simple so I didn't want to write custom CSS to manage column sizes.  I knew I could get the results I wanted with some work but I got to wondering, "how much work would it take to just integrate the library and write some JS".  I found the answer was under 10 lines of code and a little configuration work.

A quick google search led me to this codepen built by the developer of masonry.js which made things seem simple enough. 

So let's break down what I did:

  1. I already have a theme built which is using Bootstrap 3.  The theme's machine name and directory is seanreiser (replace seanreiser with your theme's machine name)
  2. Download the masonry library from here.
  3. Place masonry.pkgd.min.js in themes/seanreiser/libraries/masonry (so the file is located at themes/seanreiser/libraries/masonry/masonry.pkgd.min.js).
  4. Add the masonry library to the theme.  Add this code to my theme's seanreiser.libraries.yml :
    1. masonry:
    2.   js:
    3.   libraries/masonry/masonry.pkgd.min.js: {}
  5. Create a view:
    1. View Name : Photo Gallery
    2. Style : Unformatted List
    3. Settings -> Row Class -> col-xs-12 col-sm-6 col-md-4 col-lg-3
    4. Show: Fields
    5. Add the image to the field list.
  6. Attach the library to the views the view template  (themes/seanreiser/templates/view/views-view-unformatted--photo_gallery.html.twig)
    1. {#
    2. /**
    3.   * @file
    4.   * Default theme implementation to display a view of unformatted rows.
    5.   *
    6.   * Available variables:
    7.   * - title: The title of this group of rows. May be empty.
    8.   * - rows: A list of the view's row items.
    9.   * - attributes: The row's HTML attributes.
    10.   * - content: The row's content.
    11.   * - view: The view object.
    12.   * - default_row_class: A flag indicating whether default classes should be
    13.   * used on rows.
    14.   *
    15.   * @see template_preprocess_views_view_unformatted()
    16.   *
    17.   * @ingroup themeable
    18.   */
    19.  #}
    20.  
    21. {{ attach_library('seanreiser/masonry') }}
    22.  
    23. {% for row in rows %}
    24. {%
    25. set row_classes = [
    26. default_row_class ? 'views-row',
    27. loop.first ? 'views-row-first',
    28. loop.last ? 'views-row-last',
    29. ]
    30. %}
    31. <div {{ row.attributes.addClass(row_classes) }}>
    32. {{- row.content -}}
    33. </div>
    34. {% endfor %}
  7. To my site's themes/seanreiser/js/script.js I added:
    1. $('.views-row').masonry({
    2. itemSelector: '.views-row',
    3. percentPosition: true
    4. });
  8. Clear cache and rock and roll.

And it worked... mostly.  I had an issue where image overlapped occasionally.  The issue was that the grid would be initialized before the images were loaded.  Thankfully, David DeSandro has another library, ImagesLoaded, which detects if all your images have been loaded.  This required a couple of changes:

  1. I downloaded the library and put it in: themes/seanreiser/libraries/imagesloaded
  2. Add the imagesLoaded library to seanreiser.libraries.yml:
    1. imagesloaded:
    2.   js:
    3.   libraries/imagesloaded/imagesloaded.pkgd.min.js: {}
  3. Attach the library to the view (themes/seanreiser/templates/view/views-view-unformatted--photo_gallery.html.twig):
    1. {#
    2. /**
    3.   * @file
    4.   * Default theme implementation to display a view of unformatted rows.
    5.   *
    6.   * Available variables:
    7.   * - title: The title of this group of rows. May be empty.
    8.   * - rows: A list of the view's row items.
    9.   * - attributes: The row's HTML attributes.
    10.   * - content: The row's content.
    11.   * - view: The view object.
    12.   * - default_row_class: A flag indicating whether default classes should be
    13.   * used on rows.
    14.   *
    15.   * @see template_preprocess_views_view_unformatted()
    16.   *
    17.   * @ingroup themeable
    18.   */
    19.  #}
    20.  
    21. {{ attach_library('seanreiser/masonry') }}
    22. {{ attach_library('seanreiser/imagesloaded') }}
    23.  
    24. {% for row in rows %}
    25. {%
    26. set row_classes = [
    27. default_row_class ? 'views-row',
    28. loop.first ? 'views-row-first',
    29. loop.last ? 'views-row-last',
    30. ]
    31. %}
    32. <div {{ row.attributes.addClass(row_classes) }}>
    33. {{- row.content -}}
    34. </div>
    35. {% endfor %}
  4. Modify your JS to hold off on initially the grid until the images are loaded (themes/seanreiser/js/script.js)
    1. var $grid = $('.view-photo-gallery');
    2. $grid.imagesLoaded( function() {
    3. $grid.masonry({
    4. itemSelector: '.views-row',
    5. percentPosition: true
    6. });
    7. });

Now it's working just as I want.  Answers to some questions that I've been asked:

  • Why did you include the library manually instead of using the Masnory API module?
    Since I was using the library on one view in one theme, I didn't see the benefit in having the overhead of the module.  If, in the future I use masonry in other ways, I'll change this.
  • You mentioned photos spanning columns where is that?
    I haven't implemented that.  If I decide to do it I'll add a link here to the todo.
  • Where is the photography site?
    I'm in the middle of a major rebuild of a number of my sites.  Stay Tuned.
  • Update 4/24/2019 1:00AM EDT - You said less then 10 lines, there's a lot more there?
    My bad. views-view-unformatted--photo_gallery.html.twig is a copy of the default views-view-unformatted.html.twig with 2 lines added (the attach library). I am counting that as 2 lines.

Share and Enjoy!

    Posted: Apr 23, 2019

Cast Iron Chicken with Spinach, Mushrooms and Tomatoes

INGREDIENTS

  • 4 Chicken Thighs
  • 10 oz. Fresh Leaf Spinach
  • 1/4 cup Marsala Wine
  • 1/3 cup Chicken Stock
  • 1/4 cup Heavy Whipping Cream
  • 3 tbsp. Parmesan Cheese
  • 1/4 tsp. Lemon Juice
  • 1 tbsp. and 1/2 tsp. Minced Garlic, Separated
  • 1/2 tsp. Paprika
  • 3/4 tsp. Ground Thyme
  • Dash Garlic Powder
  • Dash Sea Salt
  • Fresh Ground Black Pepper
  • 8 oz. Fresh White Mushrooms, chopped up.
  • 5 tbsp. Butter
  • 8 oz Cherry Tomatoes

INSTRUCTIONS

  1. Set oven to 400 degrees to pre-heat.
  2. Pre-heat a 12" cast iron pan to medium heat
  3. Season chicken with paprika, salt and pepper
  4. Add 3 tbsp of butter and 1/2 tsp of the minced garlic into heated pan.
  5. Add chicken quarters and brown the skin side for 7 minutes then the back side for 5 minutes. Once done, remove chicken from stove top and set aside.
  6. Remove most of the excess liquid from pan
  7. Add the other 2 tbsp of butter. Add 1 tbsp of minced garlic, marsala wine, pepper and chicken stock to pan and allow to cook for 1 to 2 minutes. Scrape off any burnt on pieces of chicken while it cooks.
  8. Add heavy whipping cream, Parmesan cheese, lemon juice, ground thyme and mushrooms (optional) then allow to cook for 2 minutes. Add fresh spinach and dash of garlic powder and allow the spinach to cook down for 2 minutes or until wilted.
  9. Place the chicken thighs back into the pan with ingredients with the skin side up and remove from heat. Add the tomatoes between the pieces of chicken. Place pan into the oven for 20 minutes.
  10. Remove from oven, allow to cool then serve
  11. Share and Enjoy!
    Posted: Apr 17, 2019

I Hate Video Conference Calls

I have to be honest, I really don't like doing meetings over skype. Don't get me wrong there's a benefit to having video on all participants, but now I feel I have to be a television producer as well as a technologist when I'm making these calls... I spend 20 mins before each call checking the lighting, the angle of my shot, the background. And I'm worrying:

How many chins do I have in the shot? Do I need to a light to prevent a shadow?

I have to camera test shirt / tie combinations, especially with older webcams.

Why am I wearing a tie anyway? Don't these people realize that if someone is working from home the main benefit is Pajama Fridays?

I worry if my shirt clashes with the paint on the walls or worse yet, if the shirt and background are close in color and I appear to be a disembodied head? (this happened to me once)

Of course this is followed by an audio test. Is my mic too hot? Am I close enough to it. Can they hear me breathing?

IF my allergies are acting up is my nose too red? Do I need to borrow some of Anne's makeup to tone it down or will I appear to be David Bowie if I do. What about the zit from when I shaved the other day?

I have to remember to lock up the cat so I'm not trying to shoo him away from the keyboard that he'll attack in the middle of the call.

Folks, really I'm bit of a neurotic mess every time we do video calls, can we just do voice calls?

    Posted: Apr 11, 2019

Inserting a Block into a View Listing in Drupal 8

 

My blog homepage is basically an activity feed, a combination of Blog Posts, Short Notes, Images and Links, much like a facebook wall or a tumblog.  I decided I wanted to add a link to one of my other sites in the feed, basically a “house ad”.  Blatantly stealing from facebook, I decided that I wanted the second item in the feed. My goal is to create something like this:

In Drupal 7, I would have used preprocess_views_view to insert the ad into the view, but I wanted to do something that was more sustainable and not as hard coded.  Although on my blog I perform all roles (developer, designer, themes, content admin, etc), I wanted to give non-developers the ability to add, change and delete the advertisement.  So I decided to use Drupal's block interface.

I did a little investigation and found that the Twig Tweak module provides a twig function to fetch and drupal regions (and blocks, entities, fields and other Drupalisms). Here's a list of of the functions Twig Tweak provides. The drupal_region twig would do what I need.

Here’s what I did

  1. I added a region to my theme config, “view_inline_ad.”
  2. I added the block with the ad it to the region.
  3. Added the code to render the region to my views template (views-view-unformatted--blog.html.twig)
    1. {% if title %}
    2. <h3>{{ title }}</h3>
    3. {% endif %}
    4. {% for row in rows %}
    5. {%
    6. set row_classes = [
    7. default_row_class ? 'views-row',
    8. loop.first ? 'views-row-first',
    9. loop.last ? 'views-row-last',
    10. ]
    11. %}
    12.  
    13. {% if loop.index == 2 %}
    14. {{ drupal_region('view_inline_ad') }}
    15. {% endif %}
    16.  
    17. <div{{ row.attributes.addClass(row_classes) }}>
    18. {{ row.content }}
    19. </div>
    20. {% endfor %}
  4. Cleared Cache, loaded the page and rock and roll.

One problem I ran into, on my site the blog theme is not the default theme. I host multiple sites out of the same Drupal instance and am using the Switch Page Theme module to change theme based on site context. drupal_region() assumes you're using the default theme and not the current theme so it couoldn't find the region. It does accept a second parameter, theme. I popped the theme's machine name in there and it worked like a charm.

    Posted: Apr 11, 2019

Bunt, You Idiots

I posted this on Facebook 5 years ago.  It still applies today.

I've watched a lot of baseball in my life and so far this year we're seeing more infield shifts then I've ever seen before. I'm sure this is the natural evolution of the game but I have a question...

If you come up to bat and look at the infield and realize that the 3rd baseman is positioned where the shortstop normally is... Why in the name in all that is holy aren't you bunting? I get that some batters can't change their swing and go the other way... that's fine, I don’t want to change your swing. But every player should be able to square up and lay down a bunt that will roll up the 3rd base line. Push that bunt past the pitcher and you'll have an easy base hit. I don't care if you're fleet of foot like Brett Gardner or have the turtle like speed of David Ortiz, you'll make it the 90 feet before someone can get to that ball and throw you out. Do this often and one of a few things will happen:

1) The defense will stop these shifts since they don't want to give up "cheap hits".

2) You'll hit .400

Some people might say "we don't pay sluggers to bunt". I say, "if they're giving you a free base, take it". If that same slugger worked a walk you'd be applauding, "Good Eye, Good Eye". You never know what's going to start a rally.

To quote the great Yogi: "Baseball is 90% mental, the other half is physical.".

    Posted: Apr 5, 2019

Tribalism and Hate.

Food for thought:

Tribalism is the default state of humanity.  Every other form of extremist behavior is a realization of that: Racism, Homophobia, Islamophobia, antisemitism, bullying, (fill in the blank)-ophbia,  heck even the all or nothing in the political divide .. all the same thing.   We are programed to find out what's different.

We seek out what's different from us and attempt to remove it not out of hate but an unconscious survival instinct.  We are ensuring our tribe receives the resources it needs (the bottom tiers of Maslow's Hierarchy of Needs).   This instinct dates back to the days where we lived in the jungles and we competed for food, shelter, mates, etc.    The world may have changed but the genes that made it a survival instinct for thousands of years are still there and we all act on them, consciously or unconsciously.  

I am not condoning the behavior.  I am not excusing the behavior.  I am trying to understand the behavior.  

    Posted: Mar 15, 2019

The Last 4 Digits of you Social Security Number

So, you’re applying for a job and the recruiting agency asks you for your resume, wants to know when and you graduated High School and want to know your last 4 digits of your Social Security Number (for tracking purposes).  You may not realize it, but you’ve just turned over enough information to allow someone to figure out your Social Security Number.

The first 3 digits of your SSN indicate the State the SSN is issued from and the next 2 numbers (the group number) are only issued in certain years.  If you were born after 1988 a SSN was issued automatically at birth.  Prior to that most people got a SSN when they got this first job (generally sometime between their 16th and 21st birthday).  When you consider that the average person attends high school in the state they were born and graduate high school between 17 and 19 you can narrow it down so there's a 9% chance the attacker can guess your SSN in 1000 guesses.  That might sound safe but it's a trivial task to build a computer program to run the possibilities. 

The last 4 digits are the part of your SSN that’s unique and not predictable by any algorithm.  

So when organizations other than your employer, a back or the government ask you for your last 4, be aware of what you might be giving up.

    Posted: Mar 6, 2019

The Banks Are Missing a Marketing Opportunity During the Shutdown

Food for thought: The banks are missing a big good will opportunity. They could easily set up a program for federal workers. If they bring in their December pay stub, and have a FICO score over 700 the worker can get a loan. Structure it with a 2% fee up front and defer payments and interest until 15 days after the government starts issuing checks. 

So if you got paid $1000 a pay period you’d get $980 a pay period until this mess is fixed. If they walk into the bank when they get their check and sign it over to the bank there’s nothing else due.

The bank would lose a little money on the deal but gain good will. They could even waive the 2% for customers which might induce some folks to open an account with them which would be worth more to the bank in the long run than the 2%. If you market the hell out of the program they can buy a lot of brand loyalty.


UPDATE

I spoke to folks about this yesterday and I got some DMS.  Here are some additional thoughts:

  • Why a FICO score of 700?
    It's been a long while since I've needed to access credit or have done any financial coding.  I remembered that 700 was considered "good".  I was wrong 670 is "good" so 670 would be the benchmark.
     
  • Isn't using the FICO score discriminatory?
    Yes, all lending shows a bias towards people with a good credit history.  The bank has a responsibility to  their shareholders and depositors to ensure that loans are paid back.  Perhaps banks could ignore the FICO score for their current customers with Direct Deposit with the understanding that the bank is going to slurp the money back automagically when paychecks resume.
     
  • What would happen if someone didn’t pay?
    It would convert to a normal  personal unsecured loan.  I believe 24 months at around 15% would be normal.
     
  • Why the 2% fee? 
    To defray the bank’s fixed costs / administration fees.  They are already lending money below the discount rate.  Let’s face it the Payday lenders will be charging 20%.
     
  • What if people decide not to pay the loan back?  / What if people scam the system and get loans from multiple banks (if more than one bank ran similar programs)?
    The same as if someone doesn’t pay an unsecured loan back.  Court, sheriff, reposition of funds, paycheck garnishment, etc.
    Posted: Jan 12, 2019