FLOSS Project Planets
GNU tar version 1.28 is available for download.
New in this release:
The --checkpoint-action=totals option instructs tar to output the total number of bytes transferred at each checkpoint.
New conversion specifiers are implemented. Some of them take optional arguments, supplied in curly braces between the percent
sign and the specifier letter.
The option --one-top-level tells tar to extract all files into a subdirectory named by the base name of the archive (minus standard compression suffixes recognizable by --auto-compress). When used with an argument, as in --one-top-level=DIR, the files are extracted into the supplied directory. This ensures that no archive members are extracted outside of the specified directory, even if the archive is crafted so as to put them elsewhere.
The --sort=ORDER option instructs tar to sort directory entries according to ORDER. It takes effect when creating archives. Available _ORDER_s are: none (the default), name and inode. The latter may be absent, if the underlying system does not provide the necessary information.
Using --sort=name ensures the member ordering in the created archive is uniform and reproducible. Using --sort=inode reduces the number of disk seeks made when creating the archive and thus can considerably speed up archivation.
Before dumping a directory check if it contains FILE, and if so read exclude patterns for this directory from it.
Same as above, but the exclusion patterns read from FILE remain in effect for any subdirectory, recursively.
Read exclude tags from VCS ignore files, where such files exist. Supported VCS's are: CVS, Git, Bazaar, Mercurial.
This release includes official tar(1) and rmt(8) manpages. Distribution maintainers are kindly asked to use these instead of the home-made pages they have been providing so far.
After having a successful run at ski season with our VW Syncro, Trish and I figured we'd see how it performed in the summer. We took it 4x4ing in Moab, rafting in Dinosaur National Monument and camping for Father's Day Weekend. It was a trusty steed for our kids, dogs, skis and raft. Earlier this month, we planned a week-long road trip to Santa Fe to see one of my old college roommates. Because of the holiday weekend, it turned into a 10-day road trip. We left Denver in style on the morning of the 4th.
The motorcycle on the back didn't seem to slow us down much. We drove from Denver to Winter Park, taking the long way over Squaw Pass to avoid traffic.
When we arrived at our Ski Shack, the engine was making a loud knocking sound. We dismissed it as a random occurrence. When I drove to the gas station 45 minutes later, the knocking was loud enough that heads turned when I drove past. After fueling up, I started the van and began driving back to our condo. The engine sputtered, the tires screeched and then the engine died. I pulled to the side, conveniently still in the gas station's parking lot. The engine would no longer turn over.
Below is the email I sent to Mike at Rocky Mountain Westy while walking back to our condo.
Happy Fourth of July! Our van's engine gave up the ghost today. There was a loud knocking, then it felt like is
slammed on the back brakes, a screech of the tires and it died. Now it won't even turn over. Sounds like it's seized
This happened in Fraser today. I have AAA so could probably get it towed to you.
Can you help us find and install a new engine? I'd like something with similar HP. Would you recommend a 1.8T, a 3.0 liter or something else?
It was the best breakdown I've ever had. I was able to walk home (one mile) and it didn't even rain on me. From there, we continued to celebrate the 4th and refactor our road-trip plans. With the Syncro, we were planning on camping at The Great Sand Dunes, Pagosa Springs and Mesa Verde. We decided we'd drive our new sedan instead (recently gifted from Trish's Dad). I took the train to Denver, drove it up on July 5th and we departed Winter Park on Sunday, July 6.
Instead of camping in beautiful campgrounds, we changed our plans to stay at B&Bs. In the meantime, Mike replied and said he thought he'd be able to install an H6 3.0 by the end of the month. He recommended it as a good replacement for our SVX engine, particularly because it was more reliable and likely to endure more miles. We agreed to the repairs and had AAA tow it to his shop in Fort Collins.
Our first destination was The Broadmoor. We took the back way through Breckenridge and skipped the holiday traffic. We arrived around 5pm and were warmly welcomed, dogs and all. We celebrated our one-year anniversary early with excellent Italian food, golf on the West course and a fun pub crawl on Monday night.
The Broadmoor was named the #1 Golf Resort in North America by Golf magazine readers. We certainly enjoyed the course, but it's also the first time Trish and I declined beers from the cart lady. Our games were so bad, we weren't in the mood to celebrate anything.
On Tuesday afternoon, we left Colorado Springs for Pagosa Springs. There, we enjoyed a country B&B, soaked in the hot springs and had a great hike to Fourmile Falls.
On Friday, we left Taos and drove to Santa Fe, our ultimate destination. While arriving, I checked my email and was pleased to see an email from the folks working on my '66 Bus. While flipping through the pictures referenced in the email, I realized there were several videos. I did my best to get us off the road and into a place where I could watch the videos on a proper screen. You can imagine my glee as I watched my bus drive under its own power for the first time.
My "achievement unlocked!" moment was soon complimented by an excellent margarita and tasty New Mexican food. Wow! Those New Mexicans know the right level for the "default" hot sauce. Spicy and delicious!
We spent the weekend with our friends Chris, Mary and Luna and had a great time. The Santa Fe summer weather was beautiful - in the mid-70s most of the time, with nice breezes and sunshine. Trish, Chris, Sagan, Jake and I took a hike on Saturday and thoroughly enjoyed their national forest. On Sunday, we marveled at the art on display at Santa Fe's 11th Annual International Folk Art Market.More photos on Flickr &rightarrow
The rest of the time, we hung out in their backyard. Trish played her banjo, we watched the firepit crackle and Dino (their new puppy) kept us entertained with his antics. It was one of the most relaxing weekends I've had in quite some time. Thanks to Chris, Mary and Luna - you guys are awesome and we can't wait to visit again!
It has been a weekend in the spirit of headless Drupal, front-end optimizations and server side hacks. The result is I updated my blog to Drupal 8. Since you are reading this, it must mean it is live.
First let's start with the cold facts (almost chronologically ordered by request lifetime):
Other front-end technologies used that does not directly relate to the request itself:
Yeah, that's mostly just a novelty act. There is no real gain there. Quite the opposite, I have added some hacks to get around some limitations.
HHVM does not work very well with logged in users right now, but works alright for serving anonymous content.When I reload and look at the source code, there is no css loading. WAT?
Yeah, I am just assuming you remember the styles from last page load. Also, I have made it an image to have a 1 HTTP request CMS, right?No, really. How does that work?
The real magic is happening by checking if you as a user already have downloaded my page earlier. If you have, I don't need to serve you css, as far as I am concerned. You should have saved that last time, so I just take care of that.OK, so you use a cookie and save css in localstorage. Does that not screw with the varnish cache
Good question. I have some logic to internally rewrite the cached pages with a key to the same varnish hash. This way, all users trying to look at a css-less page with the css stored in localstorage will be served the same page, and php will not get touched.What a great idea!
Really? Are you really sure you have thought of all the limitations? Because they are many. But seeing as this is my personal tech blog, and I like to experiment, it went live anyway.Give us the code!
And since I am feeling pretty bad ass right now, let's end with Clint Eastwood as an animated gif.Tags:
return x * 2
>>> list(map(times2, [0, 1, 2, 3, 4]))
[0, 2, 4, 6, 8]
Yeah yeah, I know that you can do the same thing with a list comprehension or generator expression, but my point was about an independent piece of logic [like times2()] and mapping that function across a data set ([0, 1, 2, 3, 4]) to generate a new data set ([0, 2, 4, 6, 8]). However, since mapping functions like times2()aren't tied to any particular chunk of data, you can reuse them elsewhere with other unrelated (or related) data.
Along similar lines, consider function calls. You have independent functions and methods in classes. Now, think about "mapped" execution across functions. What are things that you can do with functions that don't have much to do with the behavior of the functions themselves? How about logging function calls, timing them, or some other introspective, cross-cutting behavior. Sure you can implement that behavior in each of the functions that you care about such information, however since they're so generic, it would be nice to only write that logging code just once.
Introduced in 2.4, decorators modularize cross-cutting behavior so that developers don'thave to implement near duplicates of the same piece of code for each function. Rather, Python gives them the ability to put that logic in one place and use decorators with its at-sign ("@") syntax to "map" that behavior to any function (or method). This compartmentalization of cross-cutting functionality gives Python an aspect-oriented programming flavor.
How do you do this in Python? Let's take a look at a simple example, the logging of function calls. Create a decorator function that takes a function object as its sole argument, and implement the cross-cutting functionality. In logged() below, we're just going to log function calls by making a call to the print() function each time a logged function is called.
def logged(_func): def _wrapped():
print('Function %r called at: %s' % ( _func.__name__, ctime())) return _func()
In logged(), we use the function's name (given by func.__name__) plus a timestamp from time.ctime() to build our output string. Make sure you get the right imports, time.ctime() for sure, and if using Python 2, the print() function:
from __future__ import print_function # 2.6 or 2.7 only
from time import ctime
Now that we have our logged() decorator, how do we use it? On the line above the function which you want to apply the decorator to, place an at-sign in front of the decorator name. That's followed immediately on the next line with the normal function declaration. Here's what it looks like, applied to a boring generic foo() function which just print()s it's been called.
@loggeddef foo(): print('foo() called')
When you call foo(), you can see that the decorator logged()is called first, which then calls foo() on your behalf:
$ log_func.pyFunction 'foo' called at: Sun Jul 27 04:09:37 2014foo() called
If you take a closer look at logged() above, the way the decorator works is that the decorated function is "wrapped" so that it is passed as func to the decorator then the newly-wrapped function _wrapped()is (re)assigned as foo(). That's why it now behaves the way it does when you call it.
The entire script:
'log_func.py -- demo of decorators'
from __future__ import print_function # 2.6 or 2.7 only
from time import ctime
print('Function %r called at: %s' % (
That was just a simple example to give you an idea of what decorators are. If you dig a little deeper, you'll discover one caveat is that the wrapping isn't perfect. For example, the attributes of foo() are lost, i.e., its name and docstring. If you ask for either, you'll get _wrapped()'s info instead:
>>> print("My name:", foo.__name__) # should be 'foo'!
My name: _wrapped
>>> print("Docstring:", foo.__doc__) # _wrapped's docstring!
In reality, the "@" syntax is just a shortcut. Here's what you really did, which should explain this behavior:
def foo(): print('foo() called')
foo = logged(foo) # returns _wrapped (and its attributes)
So as you can tell, it's not a complete wrap. A convenience function that ties up these loose ends is functools.wraps(). If you use it and run the same code, you will get foo()'s info. However, if you're not going to use a function's attributes while it's wrapped, it's less important to do this.
There's also support for additional features, such calling decorated functions with parameters, applying more complex decorators, applying multiple levels of decorators, and also class decorators. You can find out more about (function and method) decorators in Chapter 11 of Core Python Programming or live in my upcoming course which starts in just a few days near the San Francisco airport... there are still a few seats left!
EuroPython Society: Hi, I have a small suggestion for the Bylaws ... on all other pages of the website you abbreviate "EuroPython Society" with "EPS" but in the Bylaws you suddenly change to "EP" (in clauses 1, 2, 14, 17). You may wish to settle for "EPS
Thank you for your suggestion. In our General Assembly at EuroPython 2014 we have just voted on updating the bylaws to also use the “EPS” abbreviation.
We will update the website in the coming days.
Welp, summer vacation is over again, cycled from Nijmegen south. At the outset I said “we’ll go south till we have to speak French, and then turn around”, which meant “until Luik / Liége”. Didn’t make it that far, for the simple reason that campgrounds that are compatible with a family of cyclists with a tent are rare in that area. Instead, we cycled through Belgian Limburg, across Dutch Limburg from Maastricht to Vaals, and then back up north to Venlo. I would show a map (as I did last year with Marble), but I did my GPS logging with My Tracks on Android this time, and I’d have to spend too much time mucking about to get the data off the device for processing. Last year we rode 440km of completely flat Friesland and Groningen. This year there were hills (the Dutch Mountains!), and we weren’t sure how the kids would fare in more challenging terrain. We needn’t have worried. Mira’s “hey dad, let’s bike up the tallest mountain in the Netherlands” (322m above sea level, rising from Vaals at 160m, so this is not Tour de France material yet) was later followed by Amiel’s “hey dad, I want to ride 100km on the last day”. He’s nine years old and it took us from 10:30am to 9:00pm, but we got to the train station at Venray with 99.98km on the meter (and another 3km to go after we got off the train in Nijmegen). Still got a few days off from work-work, so I’ve decided to pick up some KDE-FreeBSD stuff again, and Tupi in particular.
This is now the sixth edition of this report. Former editions:
So, here we are with the July 2014 version, sorted by the ratio of *active* developers per million population for each country.Act: number of active developers Dev: total number of developers A/M: number of active devels per million pop. D/M: number of devels per million pop. 2009: rank in 2009 2010: rank in 2010 2011: rank in 2011 (June) 2012: rank in 2012 (June) 2013: rank in 2012 (July) 2014: rank now Code Name Population Act Dev Dev Act/Million Dev/Million 2009 2010 June 2011 June 2012 July 2013 July 2014
fi Finland 5259250 19 31 3,61 5,89 1 1 1 1 1 1
ie Ireland 4670976 13 17 2,78 3,64 13 9 6 2 2 2
nz New Zealand 4331600 11 15 2,54 3,46 4 3 5 7 7 3 * mq Martinique 396404 1 1 2,52 2,52
3 4 4 4
se Sweden 9088728 22 37 2,42 4,07 3 6 7 5 5 5
ch Switzerland 7870134 19 29 2,41 3,68 2 2 2 3 3 6 * no Norway 4973029 11 14 2,21 2,82 5 4 4 6 6 7 * at Austria 8217280 18 29 2,19 3,53 6 8 10 10 10 8 * de Germany 81471834 164 235 2,01 2,88 7 7 9 9 8 9 * lu Luxemburg 503302 1 1 1,99 1,99 8 5 8 8 9 10 * fr France 65350000 101 131 1,55 2 12 12 11 11 11 11
au Australia 22607571 32 60 1,42 2,65 9 10 12 12 12 12
be Belgium 11071483 14 17 1,26 1,54 10 11 13 13 13 13
uk United-Kingdom 62698362 77 118 1,23 1,88 14 14 14 14 14 14
nl Netherlands 16728091 18 40 1,08 2,39 11 13 15 15 15 15
ca Canada 33476688 34 63 1,02 1,88 15 15 17 16 16 16
dk Denmark 5529888 5 10 0,9 1,81 17 17 16 17 17 17
es Spain 46754784 34 56 0,73 1,2 16 16 19 18 18 18
it Italy 59464644 36 52 0,61 0,87 23 22 22 19 19 19
hu Hungary 10076062 6 12 0,6 1,19 18 25 26 20 24 20 * cz Czech Rep 10190213 6 6 0,59 0,59 21 20 21 21 20 21 * us USA 313232044 175 382 0,56 1,22 19 21 25 24 22 22
il Israel 7740900 4 6 0,52 0,78 24 24 24 25 23 23
hr Croatia 4290612 2 2 0,47 0,47 20 18 18 26 25 24 * lv Latvia 2204708 1 1 0,45 0,45 26 26 27 27 26 25 * bg Bulgaria 7364570 3 3 0,41 0,41 25 23 23 23 27 26 * sg Singapore 5183700 2 2 0,39 0,39
33 33 27 * uy Uruguay 3477778 1 2 0,29 0,58 22 27 28 28 28 28
pl Poland 38441588 11 15 0,29 0,39 29 29 30 30 30 29 * jp Japan 127078679 36 52 0,28 0,41 30 28 29 29 29 30 * lt Lithuania 3535547 1 1 0,28 0,28 28 19 20 22 21 31 * gr Greece 10787690 3 4 0,28 0,37 33 38 34 35 35 32 * cr Costa Rica 4301712 1 1 0,23 0,23 31 30 31 31 31 33 * by Belarus 9577552 2 2 0,21 0,21 35 36 39 39 32 34 * ar Argentina 40677348 8 10 0,2 0,25 34 33 35 32 37 35 * pt Portugal 10561614 2 4 0,19 0,38 27 32 32 34 34 36 * sk Slovakia 5477038 1 1 0,18 0,18 32 31 33 36 36 37 * rs Serbia 7186862 1 1 0,14 0,14
tw Taiwan 23040040 3 3 0,13 0,13 37 34 37 37 39 39
br Brazil 192376496 18 21 0,09 0,11 36 35 38 38 40 40
cu Cuba 11241161 1 1 0,09 0,09
38 41 41 41 41
co Colombia 45566856 4 5 0,09 0,11 41 44 46 47 46 42 * kr South Korea 48754657 4 6 0,08 0,12 39 39 42 42 42 43 * gt Guatemala 13824463 1 1 0,07 0,07
43 44 * ec Ecuador 15007343 1 1 0,07 0,07
40 43 43 45 45
cl Chile 16746491 1 2 0,06 0,12 42 41 44 44 47 46 * za South Africa 50590000 3 10 0,06 0,2 38 48 48 48 48 47 * ru Russia 143030106 8 9 0,06 0,06 43 42 47 45 49 48 * mg Madagascar 21281844 1 1 0,05 0,05 44 37 40 40 50 49 * ro Romania 21904551 1 2 0,05 0,09 45 43 45 46 51 50 * ve Venezuela 28047938 1 1 0,04 0,04 40 45 50 49 44 51 * my Malaysia 28250000 1 1 0,04 0,04
49 50 52 52
pe Peru 29907003 1 1 0,03 0,03 46 46 51 51 53 53
tr Turkey 74724269 2 2 0,03 0,03 47 47 52 52 54 54
ua Ukraine 45134707 1 1 0,02 0,02 48 53 58 59 55 55
th Thailand 66720153 1 2 0,01 0,03 50 50 54 54 56 56
eg Egypt 80081093 1 3 0,01 0,04 51 51 55 55 57 57
mx Mexico 112336538 1 1 0,01 0,01 49 49 53 53 58 58
cn China 1344413526 10 14 0,01 0,01 53 53 57 56 59 59
in India 1210193422 8 9 0,01 0,01 52 52 56 57 60 60
sv El Salvador 7066403 0 1 0 0,14
36 58 61 61
969 1561 62,08%
A few interesting facts:
- New Zealand bumps from rank 7 to rank 3, thanks to one new active developer
- Switzerland loses one developer and goes donw to rank 6
- Norway also slightly goes down by losing one developer
- With two more developers, Austria climbs up to rank 8 and overtakes Germany...;-)
- Hungary climbs a little bit by gaining one developer
- Singapore doubles its number of developers from 1 to 2 and bumps from 33 to 27
- One rank up too for Poland that gained one developer
- Down to rank 31 for Lithuania by losing one developer
- Up to rank 32 for Greece with 4 developers instead of 3
- Argentina goes up by havign two more developers (it lost 2 last year)
- Up from 46 to 42 for Colombia by winning one more developer
- One more developer and Russia climps from 49 to 48
- One less for Venezuela that has only one developer left...:-(
- No new country this year. Less movement towards "the universal OS"?
- We have 12 more active Debian developers and 26 more developers overall. Less progression than last year
- The ratio of active developers increases is nearly stable though slightly decreasing
I have described each and every options in detail below and here is the summery.
- Axis2 services as standalone WAR applications.
- Axis2 services as standalone WAR applications using AS default Axis2 runtime environment.
- Axis2 services as WAR applications using custom Axis2 runtime environment.
- Axis2 services as AAR applications using AS default Axis2 runtime environment.
- Axis2 services as AAR applications using custom Axis2 runtime environment.
WSO2 AS 5.2.1 version is distributed with Axis2 1..6.1 plus some custom patches. Assume one wants to use Apache Axis2 1.7.0 on WSO2 AS 5.2.1.
Note - Axis2 1.7.0 yet to be released hence I use Axis2 1.7.0-SNAPSHOT version for this post but what ever the details I cover here are common for any Axis2 version.
Note - In case if you use WSO2 AS 5.2.1, 5.2.0 or 5.1.0 versions you need to do following additional steps.
a. Open AS-HOME/repository/conf/tomcat/webapp-classloading-environments.xml file.
b. Find <DelegatedEnvironment> with name "Carbon", replace it with following configuration.
1. Axis2 services as standalone WAR applications.
In fact here I don't need to mention any thing special you can think Axis2 as just another web framework and develop your service and deploy as a WAR file just like you develop any other web application such Spring, Apache Wicket, Apache Structs etc.
If you are a novice to Axis2 you can easily start with Axis2 web application Maven archetype, I have covered details about this Maven archetype here. Also you can find complete working sample from here.
Once you build this sample application you can deploy to WSO2 AS as a web application. Once you done that it is possible to access WSDL through following url.
2. Axis2 services as standalone WAR applications using AS default Axis2 runtime environment.
If you open and inspect WEB-INF/lib directory of above sample you can find number of Axis2 jar files and their dependencies. Size of the WAR file can be vary from 8MB to 10 MB or so on. This is ok if you deploy one or two services but in case if you deploy large number of services then packaging dependencies with each and every WAR file may not convenient and can be a extra overhead too.
The solution for this is to use default Axis2 runtime environment or add a new custom runtime environment (CRE) for Axis2. Under this point I cover first option and next point cover 2nd option by creating a custom CRE. In both approaches you don't need to duplicate any Axis2 or dependent Jar file inside WEB-INF/lib directory you have to include your application specific Jar files only.
Further in both approaches we use webapp-classloading.xml file to define runtime environment for the service. webapp-classloading.xml file is WSO2 AS specific application descriptor and it is expected to present on META-INF directory in case of a runtime environment customisation like this.
You can find complete working example for this option from here. Download, build and deploy this service then you can access to WSDL file in following URL.
If you open webapp-classloading.xml file you should able to see following entry.
Please note in this example we consumed default Axis2 version shipped with WSO2 AS.
3. Axis2 services as WAR applications using custom Axis2 runtime environment.
As I explained earlier here also we don't package any Axis2 related Jar file inside the service. The main difference from previous one is here we create a new CRE, which means you can bring any Axis2 version you want and share with your service just like you share default Axis2 runtime. Following are the required steps.
a. Download required Axis2 version from Apache Axis2 web site here. (Let's say Axis2-1.7.0-SNAPSHOT.zip )
b. Create a new directory called "axis217" under "AS-HOME/lib/runtimes" . We generally use "AS-HOME/lib/runtimes" directory to keep Jar files belong to custom runtimes.
c. Extract downloaded Axis2-1.7.0-SNAPSHOT.zip file and copy all jar files available on "Axis2-1.7.0-SNAPSHOT/lib" directory to above created AS-HOME/lib/runtimes/axis217" directory.
d. Open AS-HOME/repository/conf/tomcat/webapp-classloading-environments.xml file and add following entry which define a new CRE for Axis2 1.7.0-SNAPSHOT version.
e. Download complete example code from here.
f. Build and deploy to WSO2 AS, you can access WSDL file through following url.
Like in previous example if you open the webapp-classloading.xml file under META-INF directory of the sample service you should able to see following entry. This is how we refer "Axis217" CRE we just created inside the web service ( this allows applications/services to load required Axis2 dependencies from "Axis217" CRE ).
4. Axis2 services as AAR applications using AS default Axis2 runtime environment.
So far for above examples we used WAR packaging but now let's look at how you could develop Axis2 service as a AAR archive and deploy.
In this AAR option first we have to deploy axis2.war file then deploy .AAR file through the admin interface provided by the Axis2. Here axis2.war application act as container within the WSO2 AS. For this approach also we could use default Axis2 runtime, please refer following procedure.
a. Download web archive version (WAR) of Axis2 from Apache Axis2 web site.
b. Extract axis2.war file and perform following modifications.
c. As we will use default Axis2 version available with WSO2 AS remove "lib" directory from extracted axis2 directory.
d. In order to use default Axis2 runtime, create a file called webapp-classloading.xml with following content.
e. re-archive Axis2 directory as axis2.war and deploy into WSO2 AS.
Now you should able to see Axis2 admin console through following url which can be used to upload your AAR services.
Here is WSDL url for default version sample.
Note - If you use WSO2 AS 5.2.1 or previous version it may possible to get few JSP rendering issues on above mentioned Axis2 admin console but those are not affect to any service invocations.
5. Deploy web service as AAR file using custom Axis2 runtime environment.
This approach is also similar to previous one but instead of default Axis2 runtime we use Axis2 dependencies available with axis2.war distribution. Please refer following procedure.
a. Download web archive version (WAR) of Axis2 from Apache Axis2 web site.
b. Deploy axis2.war file into WSO2 AS.
Now you should able to see Axis2 admin console through following url which can be used to upload your AAR services.
Here is WSDL url for default version sample.
Note - If you use WSO2 AS 5.2.1 or previous version it may possible to get few JSP rendering issues on above mentioned Axis2 admin console but those are not affect to any service invocations.
I continue to write some scripts:
- convert-ktempdir.pl. It will allow to port from KTempDir to QTemporaryDir
- convert-ktemporaryfile.pl. It will allow to port from KTemporaryFile to QTemporaryFile
- convert-qt-os-macro.pl. Q_WS_* was replaced by Q_OS_*
- convert-kmd5.pl. Now we use QCryptographicHash(QCryptographicHash::Md5)
- convert-kdoublenuminput.pl. It converts from KDoubleNumInput to QSpinBox
And there was some fix in other scripts.
I will continue to create new script.
2013 was an amazing year: Trish and I got married, celebrated on a 'round-the-world honeymoon and invested in a new 4x4 VW Bus. I finally achieved my goal of vacationing 25% and I got to spend more than two months in the presence of my wonderful parents.
For the last few years, I've generally had one client per year. That changed this year when my contract with Oracle ended in May. Fortunately, I had the opportunity to develop a cool dashboard application before I finished. I wrote about it in a four-part series.
- Developing with AngularJS - Part I: The Basics
- Developing with AngularJS - Part II: Dialogs and Data
- Developing with AngularJS - Part III: Services
- Developing with AngularJS - Part IV: Making it Pop
I engaged in a month-long contract with Travelport to keep me busy in June. They hired me to develop a portal consolidation prototype, which I did with AngularJS, Grails and LDAP. I showcased that application at Devoxx in November.
In September, I started a new gig with John Muir Health. I was hired to help with their mobile architecture, and spent my first couple months doing front-end optimizing and helping get their MyJMH product released. Once the release was complete, I proposed a mobile architecture and started assisting with the development of their mobile application.
We're developing the Mobile API with Spring Boot. I wrote about my initial experience in A Webapp Makeover with Spring 4 and Spring Boot. My contract with John Muir Health is through the end of March and I hope to start something new shortly after.
- JavaOne 2013 Roundup: Java 8 is Revolutionary, Java is back
- Netty 4 Reduces GC Overhead by 5x at Twitter
- Spring 4 Enhances Support for Java 8, Java EE 7, REST and HTML5
I spoke at five events in 2013:
- Denver JUG on The Modern Java Web Developer and Java Web Security
- Devoxx France on Comparing JVM Web Frameworks and Play vs. Grails
- HTML5 Denver on Bootstrap
- JavaOne: I spoke for the first time and received a Rock Star Award
- Devoxx and a Nordic Countries Speaking Tour on The Modern Java Web Developer
It seems that folks liked my presentations since they were in the top 1% of most viewed on SlideShare in 2013.
Trish took many beautiful photos as part of our trip to Devoxx France.
We stopped in Iceland on the way home to see the Northern Lights.
AppFuse: I released AppFuse Light 2.2.1 in January and switched AppFuse from JSF's MyFaces to PrimeFaces in February. I blogged about AppFuse's GWT integration in March and celebrated the project's 10 year anniversary in April. AppFuse 3.0 was released just before Christmas.
Roller: I didn't contribute any code to the Roller project in 2013, but I did make this site responsive with CSS media queries.Personal
Trish and I started our world travels in March with a trip to Magnificent Mexico. We had a wonderful time playing with old friends and renting a house on the beach.
Our trip to Paris and Iceland was a dream come true for Trish. Watching the Aurora Borealis dance in the sky is something I'll never forget.
To end the ski season in April, we completed the trifecta (3 ski resorts in 3 days) with a fun family weekend.
The last week of the ski season was epic, as I described in a life update.
The last week in Winter Park was the best skiing of the year. The first (Tuesday) afternoon, I started skiing around 1pm and it snowed all afternoon - resulting in several inches by the end of the day. The next day was smooth and empty, followed by a day of deep powder and knee-deep runs down Eagle Wind. I had one of the best runs of my life that day.
I wrote about the '66 Bus Project and how I removed it from Motorworks Restorations after six years.
We spent the first weekends in June on the Colorado River. One of the biggest highlights for me was catching a 16" Trout, right after Trish saw it jump and told me exactly where to cast my line. The fact that I was able to cast it to the precise spot was cool enough, but getting the fish on my line moments later was exhilarating. Shortly after, a majestic Bald Eagle flew over us and we all dropped our jaws in amazement.
Trish and I started a two month sabbatical in July to get married in proper fashion in the town I grew up in. She looked absolutely stunning.
During the ceremony, I surprised her with a 162-page book I built with my words and her pictures.
When asked if I'd take her as my lawfully-wedded wife, I shouted as "YES!" at the top of my lungs. Trish agreed enthusiastically and we were pronounced husband and wife.
Our wedding week was an unbelievably fun experience with many, many friends and family. We look forward to celebrating it over and over again as long as we live.
We had a day of rest following the wedding, then drove back to Denver to begin our 'round-the-world honeymoon without phones. We spent a month traveling to Ireland, Italy, Thailand and Fiji. It was a wonderful journey and we greatly enjoyed all the people, places and experiences.
We arrived back in the US at the end of August, just in time to celebrate Jack's 9th birthday.
In September, we got loud at the Broncos Home Opener, and experienced beautiful Colorado fall weather with trips to Estes Park and Aspen. In October, we traveled to Minnesota for a best friend's wedding. We also visited Pennsylvania to spend some time with Trish's parents.
In early December, we flew to Idaho to pickup our new Syncro. We anticipated a few VW Adventures when we bought the bus and haven't been disappointed.
The Syncro drove back to Denver just fine, but started experiencing cooling issues driving around town. We got it fixed and drove to Montana for Christmas. We broke down on Christmas Eve in Bozeman, tried to fix it, but eventually gave up and rented a car. Straightaway Motors replaced the thermostat over the next week and we were able to drive it back to Denver with no issues. It started overheating again a couple days later. We've only recently got it running smoothly, with help from Rocky Mountain Westy. You can read the full story on thesamba.com.
Christmas Vacation was spent at The Raible Homestead, enjoying my parents new retirement cabin and a sweet sledding hill.
We finished the year skiing at Big Mountain, where I learned how to downhill ski in grade school.2014
My goal for 2014 is singular: finish The Bus. I finally found the restoration shop I wish I would've found years ago. They're very quick and efficient, and send me daily (picture) updates of their progress. With any luck, it'll be done in a couple months (sound familiar?).
Last year, I wanted to slow down and I feel like I did that on our honeymoon. My wife scoffs at that notion. This year, I hope to simply take more time to do things, instead of trying to cram many things into tight timelines.
I plan to spend less time traveling and speaking at conferences and more time at Volkswagen shows. With our 4x4 VW Syncro, we hope to camp, raft and spend quite a bit of time in the Rocky Mountains. We also hope to take the busses to a few art shows to show off Trish's majestic photos.
Last year, and the year before, we watched the Broncos fail miserably in the NFL playoffs. This year, they're in the Super Bowl. With a kick-ass Ski Bus, a Porsche Bus on the way, awesome kids and a great wife - 2014 is destined to be spectacular. I hope the Broncos are too!
The last months I was busy with a friends art project. Today I'm very happy to announce that it went public on july 15th and is doing good so far.
Jule, the founder of Port of Art, approached me last summer, asking if I could help her building an online market place for artworks. Working primarily as a freelance Drupal developer, knowing that her budget is tight and that she is certainly not the first one with this idea, I hesitated. But I gave it a thought and after several meetings I agreed. I liked the idea and I liked Jules approach, that is very trusting and positive without being naive. I like good people ;) She also gave me the impression of being able to value constructive input, even if it means to change previous ideas. That is a good feature in clients!Basic ideas with a special flavor
The basic requirements were pretty simple:
- Content management for static content pages as well as for special content like the artworks that are sold on the site
- Search artworks by different filters
- Legal compliant checkout process
- Integration of external payment providers (limited to paypal for the moment being)
- Contact forms
- Multilingual content and communication
- Integration of social media
- Some map views for geo visualization
- SEO, customizability, ...
So far that was relatively straight forward and we all love Drupal for that.
But there were some special requirements too, that had a huge impact on my choice of modules to realize this with.
- Artworks don't integrate with a basic warehouse approach. Each one should be unique and can be bought only once. Therefor there was no need for a shopping cart either.
- Artworks can be bought for a fixed price or as an auction.
- Artworks under a certain price are not sold via the site, but instead the customer and the artist are put in touch directly and have to figure out the details independently of the platform.
- Artists should be able to upload their artworks, pay a fee to get them published and than manage the selling and delivery on their own.
- Artworks expire after a certain time that depends on the publishing fee that the artist is willing to pay.
- Once an artwork has been sold on the site, an additional fee has to be paid.
- Fully customizable e-mails
The main content is obviously the artwork. This is a node type with additional fields to represent attributes of an artwork. Then there are static pages, artschools, faqs and webforms. On the user side we have two frontend user roles for customers and artists that get enhanced using the Profile 2 module.Additional considerations
The situation that our development team was faced with: Small budget, tiny team (only 2 people), the project's concept still a little in the flux. The founder had no technical background or previous experience using Drupal but needed a customized shop system that she could actually manage after we finished the project and went on to other things. So one of the goals during development has always been to make things configurable. Special text at a certain page? Build a setting for that. A special criterion that controls logic during checkout? Don't hardcode it somewhere! Build a setting for that as it might change later and you don't want to change code for simple things. I love drupal for it's easy variable management and quick form building capabilities. Building an admin form to control certain behaviors takes rarely more then 10 minutes. Obviously there are things that you can't build that way, but when you can, do it. I feel much butter with it and the client loves it too because it gives him control.Conception and development process
One of the things I knew before, but that got confirmed again: Communication is the key. The client has never did a web project before. That meant that certain good practices and workflow, concerning the development process as well as the final product, were not clear to her. So we (the designer and me) spend a good amount of time helping her figure out what was realistic and which compromises needed to be done in order to deliver the product without cost explosion or an exagerated time frame. Being honest and communicating potential problems early on, as well as the clients openness towards constructive input, was something that attributed a lot to the perceived quality of the development process. Including the client in the development and design decisions also allowed us to educate her on the technical aspects of the product and raise awarness about technical implications, making her see advantages and restrictions in different areas that she didn't consider in the beginning.
We didn't formalize the process, but we ended up with some kind of agile development with three distinct roles: Conception and design by the client, frontend by the designer and backend logic and architecural design by me. That worked very good for us.
First, there is Rules. A crazy wonderland for workflow configuration that amazes me every time I look at it. But I've almost never used it. Call me old fashioned, but when business logic or complex relations must be build, I prefer to build them on my own. I want as much logic as possible in the code, not in the database. So for all the power Rules provide, I still prefer not to use it.
Then there is Commerce. We have never build a real-world website with it, so our experience was very limited. We thought about it. Very seriously. Then we decided against it. From todays perspective that was probably an error. But given the special requirements we were afraid of having to spent too much time customizing and altering the workflow that commerce proposes. This was more of a gut feeling. And at the end I'm not sure it was the right decision. We ended up with conceiving and building a full fledged product management incuding the purchase logic and payment. The obvious advantage when you write something like this on your own, is that you have a lot of fine grained control about flow and design. But the price is pretty high considering the amount of time necessary. At the end we have a considerable code base that needs to be maintained. So next time, I hope I'll remember this an give commerce a more in depth examination regarding the potential for the problem at hand.Crucial contrib modules / add ons
It's hardly necessary to mention, but we couldn't have build the site so easily without the usual candidates: Views, Webform, Better Exposed Filters, Address Field, CTools, i18n, References, Profile 2, Geofield, Global Redirect, Libraries, ...
The fantastic wookmark jquery plugin is responsible for the display of the central search component of the site. Our designer loves it!Some modules that got born or advanced
I build MEFIBS for this site. I had a need for that functionality before, but never quite as strong as this time, so I decided to solve it as a self contained module instead of hacking things together. Though there are some problems currently with a few new features that I added recently, it is already in production and doing pretty well. Have a look at the filter and sorting blocks on the artwork search page: . Two independant blocks without duplicating a views display or intensive custom form altering. That's pretty neat.
Hopefully the jQuery Update module will also profit. During development I ran into issues with the admin version feature introduced here: https://www.drupal.org/node/1524944. I wrote about it in jQuery version per theme. This resulted in a feature patch that is currently on a good way to get committed soon.
Another module I find myself using often is my sandbox module Mailer API. It's a bit cumbersome to use as a developer, but for the client it's perfect. She can customize practically every mail that will be send by the system. It's all on a single configuration page and supports multilingual setups. A test mail feature is also included to see what mails will look like. And a batch mailer that the client often uses to address a bunch of people. It's like very easy home made promotional mails in a consistent look and feel. Made the client happy.
For frontend eye candy we have build a jQuery plugin that is responsible for the collapsible checkbox filter elements in the left side bar.Some module discoveries
During the work on www.port-of-art.com I found some modules that I didn't know before.
The Form API Validation module allows you to simplify validation rules in custom forms, using predefined validation rules. And you can also add your own rules which we used for the price entry validation needed when artists publish their artworks.
The Physical Fields module provides fields for physical dimensions and for weight attributes. That was exactly what we needed for physical goods. It saved us the time to configure fields in field collections.Conclusion
At the end of the project I can say, that everyone involved has had a good and productive time and enjoyed the process and the result. The client is happy for all the things she can do with the site. Now she can concentrate on managing business and extending marketing. The designer was happy. Even if some of the design decisions might not have been the best ones looking at the requirements profile from today. I feel positive though that the system fully matches the clients expectations and that it'll be a valuable tool for developing her business. If the site manages to establish itself, it's more than probable that we would rebuild the system, at least some substantial pieces like the shop component.
We as the site builders are happy too. We feel that we have done a good job and that we managed to keep resources and expectations in balance. I would do it again, which always feels like a good measure.Category: Drupal Planet7.x
The original version of this photo is available on her website. Her description:
I love this photo I took of Stranahan's Colorado Whiskey Truck and Distillery last spring. Rob Dietrich is the head distiller of Stranahan's Colorado Whiskey and this is his 1938 Dodge that John "the Duke" Wayne used to drive when he stayed in Aspen, Colorado.
Way to go baby! You're awesome!
It's fair to say, on a fresh install the content authoring experience in Drupal needs improvement. WYSIWYG editors are often criticised for various reason such as the ugly HTML they are known to generate or the power they give users to mess up typography. While these are valid criticisms, there is definitely a right and wrong way configure these editors. Doing things the right way will empower users while keeping them safe from nasty pitfalls. Note: this guide assumes you're already familiar with a typical Drupal WYSIWYG setup.Provide a true WYSIWYG experience
It's important that a WYSWIYG editor represents exactly what appears on the front-end of your website. While it seems obvious, it's easy to ignore and has a big impact on a user's experience.
Our WYSWIYG stack is:
Unless you are over 60, you weren't promised flying cars. You were promised an oppressive cyberpunk dystopia. Here you go.
(Source: found in the soup)
Luckily the future today is still unwritten. Shape it well.
Every web based product is adding “responsive design” to their feature lists. Unfortunately in many cases that responsive design is actually making their product much harder to use on a variety of screen sizes instead of easier.
The problem is that common CSS libraries and grid systems, including the extremely popular bootstrap, imply that a design can be made responsive using fixed cut-off points and the design just automatically adjusts. In reality making a design responsive requires tailoring the cut off points so that the design adjusts at the points where it stops working well.
For example, let’s look at the bootstrap documentation and in particular the top menu it uses. The bootstrap documentation gets it right, we can shrink the window down right to the point where the menus only just fit and they stick to the full size design:
If we shrink the window further the menus wouldn’t fit anymore so they correctly switch to the hamburger style:
That’s the right way to do it. The cutoff points have been specifically tailored for the content. There are other stylistic changes as well as these structural ones – the designer believes that centred text works better for headings on smaller screens for example. That’s fine, they’re fairly arbitrary design decisions based on what the designer believes looks best. I’m focussed on structural issues.
To see what happens if we ignore let’s pretend that we add a new menu item:
But now when we shrink the window down, the breakpoint is in the wrong place:
Now the design breaks as we shrink the window because the break point hasn’t been specifically tailored to the content. This is the type of error that regularly happens when people think that a responsive grid system can automatically make their site responsive. The repercussions in this case aren’t particularly bad, but it can be significantly worse.
Recently Jenkins released a rewrite of their UI moving it to using bootstrap which has unfortunately gotten responsive design completely wrong (and sadly I’m yet to see anything it’s actually improved). Browser widths that used to work perfectly well with the desktop only site are now treated as mobile browsers and content wraps into a long column. What’s worse, the most useless content, the sidebar, is what’s shown at the top with the main content pushed way down the page. At other widths the design doesn’t fit but doesn’t wrap leaving some links completely inaccessible.
It would be much better if people stopped jumping on the responsive design bandwagon and just designed their site to work for desktop browsers unless they are prepared to fully invest and do responsive design right. Mobile browsers are designed to work well with sites designed for desktop and have lots of tools and techniques for coping with them. As you add responsive design and other adjustments designed for mobile you take responsibility for making the design work well everywhere from the browser onto yourself. Using predefined breakpoints from a CSS library is unlikely to give the result you intend. It would be nice if CSS libraries stopped claiming that it will.
I am still looking for a good e-mail replacement that is more respectful of my privacy.
This will never happen with the existing e-mail system due to the way it works: when you send an e-mail to someone, even if you encrypt the body of your e-mail, the metadata will transit from server to server in clear, and the final destination will store it.
Every PGP UX I have tried is terrible anyways. It's just too painful to get things right for someone that has no knowledge (and no desire to have some) of how things work.
What I aiming for now is a separate system to send and receive mails with my close friends and my family. Something that my mother can use like regular e-mails, without any extra work.
I guess some kind of "Darknet for E-mails" where they are no intermediate servers between my mailbox and my mom's mailbox, and no way for a eavesdropper to get the content.
- end-to-end encryption
- direct network link between my mom's mail server and me
- based on existing protocols (SMTP/IMAP/POP3) so my mom can use Thunderbird or I can set her up a Zimbra server.
The Tox Project is a project that aims to replace Skype with a more secured instant messaging system. You can send text, voice and even video messages to your friends.
The other main feature of Tox is its Distributed Hash Table that contains the list of nodes that are connected to the network with their Tox Id.
When you run a Tox-based application, you become part of the Tox network by registering to a few known public nodes.
To send a message to someone, you have to know their Tox Id and send a crypted message using the crypto_box api and the keypair magic.
Tox was created as an instant messaging system, so it has features to add/remove/invite friends, create groups etc. but its core capability is to let you reach out another node given its id, and communicate with it. And that can be any kind of communication.
So e-mails could transit through Tox nodes.Toxmail experiment
Toxmail is my little experiment to build a secure e-mail system on the top of Tox.
It's a daemon that registers to the Tox network and runs an SMTP service that converts outgoing e-mails to text messages that are sent through Tox. It also converts incoming text messages back into e-mails and stores them in a local Maildir.
Toxmail also runs a simple POP3 server, so it's actually a full stack that can be used through an e-mail client like Thunderbird.
You can just create a new account in Thunderbird, point it to the Toxmail SMPT and POP3 local services, and use it like another e-mail account.
When you want to send someone an e-mail, you have to know their Tox Id, and use TOXID@tox as the recipient.
When the SMTP daemon sees this, it tries to send the e-mail to that Tox-ID. What I am planning to do is to have an automatic conversion of regular e-mails using a lookup table the user can maintain. A list of contacts where you provide for each entry an e-mail and a tox id.
End-to-end encryption, no intermediates between the user and the recipient. Ya!Caveats & Limitations
For ToxMail to work, it needs to be registered to the Tox network all the time.
This limitation can be partially solved by adding in the SMTP daemon a retry feature: if the recipient's node is offline, the mail is stored and it tries to send it later.
But for the e-mail to go through, the two nodes have to be online at the same time at some point.
Maybe a good way to solve this would be to have Toxmail run into a Raspberry-PI plugged into the home internet box. That'd make sense actually: run your own little mail server for all your family/friends conversations.
One major problem though is what to do with e-mails that are to be sent to recipients that are part of your toxmail contact list, but also to recipients that are not using Toxmail. I guess the best thing to do is to fallback to the regular routing in that case, and let the user know.
Anyways, lots of fun playing with this on my spare time.
The prototype is being built here, using Python and the PyTox binding:
It has reached a state where you can actually send and receive e-mails :)
I'd love to have feedback on this little project.
For a Python project I'm working on, I wrote a parent class with multiple child classes, each of which made use of various modules that were imported in the parent class. A quick solution to making these modules available in the child classes would be to use wildcard imports in the child classes:from package.parent import *
however, PEP8 warns against this stating "they make it unclear which names are present in the namespace, confusing both readers and many automated tools."
For example, suppose we have three files:# a.py import module1 class A(object): def __init__(): pass # b.py import module2 class B(A): def __init__(): super(B, self).__init__() # c.py class C(B): def __init__(): super(C, self).__init__()
To someone reading just b.py or c.py, it is unknown that module1 is present in the namespace of B and that both module1 and module2 are present in the namespace of C. So, following PEP8, I just explicitly imported any module needed in each child class. Because in my case there were many imports and because it seemed repetitive to have all those imports duplicated in each of the many child classes, I wanted to find out if there was a better solution. While I still don't know if there is, I did go down the road of how imports work in Python, at least for 3.4.1, and will share my notes with you.
Python allows you to import modules using the import statement, the built-in function __import__(), and the function importlib.import_module(). The differences between these are:
The import statement first "searches for the named module, then it binds the results of that search to a name in the local scope" (Python Documentation). Example:Python 3.4.1 (default, Jul 15 2014, 13:05:56) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import re >>> re <module 're' from '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/re.py'> >>> re.sub('s', '', 'bananas') 'banana'
Here the import statement searches for a module named re then binds the result to the variable named re. You can then call re module functions with re.function_name().
A call to function __import__() performs the module search but not the binding; that is left to you. Example:>>> muh_regex = __import__('re') >>> muh_regex <module 're' from '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/re.py'> >>> muh_regex.sub('s', '', 'bananas') 'banana'
Your third option is to use importlib.import_module() which, like __import__(), only performs the search:>>> import importlib >>> muh_regex = importlib.import_module('re') >>> muh_regex <module 're' from '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/re.py'> >>> muh_regex.sub('s', '', 'bananas') 'banana'
Let's now talk about how Python searches for modules. The first place it looks is in sys.modules, which is a dictionary that caches previously imported modules:>>> import sys >>> 're' in sys.modules False >>> import re >>> 're' in sys.modules True >>> sys.modules['re'] <module 're' from '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/re.py'>
If the module is not found in sys.modules Python searches sys.meta_path, which is a list that contains finder objects. Finders, along with loaders, are objects in Python's import protocol. The job of a finder is to return a module spec, using method find_spec(), containing the module's import-related information which the loader then uses to load the actual module. Let's see what I have in my sys.meta_path:>>> sys.meta_path [<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib.PathFinder'>]
Python will use each finder object in sys.meta_path until the module is found and will raise an ImportError if it is not found. Let's call find_spec() with parameter 're' on each of these finder objects:>>> sys.meta_path.find_spec('re') >>> sys.meta_path.find_spec('re') >>> sys.meta_path.find_spec('re') ModuleSpec(name='re', loader=_frozen_importlib.SourceFileLoader object at 0x7ff7eb314438>, origin='/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/re.py')
The first finder knows how to find built-in modules and since re is not a built-in module, it returns None.>>> 're' in sys.builtin_module_names False
The second finder knows how to find frozen modules, which re is not. The third knows how to find modules from a list of path entries called an import path. For re the import path is sys.path but for subpackages the import path can be the parent's __path__ attribute.>>>sys.path ['', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/site-packages/distribute-0.6.49-py3.4.egg', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python34.zip', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/plat-linux', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/lib-dynload', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/site-packages', '/home/miguel/.pythonbrew/pythons/Python-3.4.1/lib/python3.4/site-packages/setuptools-0.6c11-py3.4.egg-info']
Once the module spec is found, the loading machinery takes over. That's as far as I dug but you can read more about the loading process by reading the documentation.
Concern Worldwide is a leading international humanitarian organization dedicated to tackling poverty and suffering in the world’s poorest countries. Their main website, www.concern.net, plays an important role in their fundraising process. It enables people from around the world to donate towards specific campaigns and ensure that their money is distributed to where it’s needed most.
SystemSeed has the wonderful opportunity of partnering with Concern in leveraging Drupal to power the Concern Worldwide platform for a number of years spanning all the way back to the days of Drupal 5. This particular site was upgraded to Drupal 7 in 2012 as part of a large platform refactor which aimed to consolidate all of Concern’s Drupal websites under a single common platform. We wrote about the transition from standalone sites in this case study.
Since then, we have been leading a large project to bring full responsiveness and optimisations across a wide spectrum of devices to all sites on that platform. Today (July 3, 2014) sees the completion of this project with the rollout of a fully responsive and adaptive theme layer, catering for its widest audience ever. In this case study, we’ll look at some of the components of this project, the processes, the challenges, the successes, and lessons learned along the way.Key modules/theme/distribution used: OmegaBreakpointsBreakpoint PanelsPictureInline Form ErrorsOrganizations involved: SystemSeedTeam members: mrfeltonrahulbileroblavfastangeljucallme
I have been asked to publish bug stats from time to time. Not exactly sure about the schedule yet, but I will try and stick to Fridays, as in the past; this is for the obvious reason that it makes historical data easier to compare. "Last Friday of each month" may or may not be too much. Time will tell.
The UDD bugs interface currently knows about the following release critical bugs:
- In Total:
- Affecting Jessie:
431 That's the number we need to get down to zero
before the release. They can be split in two big categories:
- Affecting Jessie and unstable:
383 Those need someone to find a fix, or to finish the
work to upload a fix to unstable:
- 44 bugs are tagged 'patch'. Please help by reviewing the patches, and (if you are a DD) by uploading them.
- 20 bugs are marked as done, but still affect unstable. This can happen due to missing builds on some architectures, for example. Help investigate!
- 319 bugs are neither tagged patch, nor marked done. Help make a first step towards resolution!
- Affecting Jessie only: 48 Those are already fixed in unstable, but the fix still needs to migrate to Jessie. You can help by submitting unblock requests for fixed packages, by investigating why packages do not migrate, or by reviewing submitted unblock requests.
- Affecting Jessie and unstable: 383 Those need someone to find a fix, or to finish the work to upload a fix to unstable:
- Affecting Jessie: 431 That's the number we need to get down to zero before the release. They can be split in two big categories:
So I am not kidding NavBar is literally the next step in Drupal navigation, it is being used in core for Drupal 8. This is great news because not only does it mean that the Drupal 8 core will contain some much needed improvements to the administration navigation scheme. Back end user improvements like this are perhaps the thing that makes me most excited about what Drupal 8 is bringing to the table. Lets look a little bit at NavBar.
What You Get
Pretty simply put NavBar gets you a responsive administration toolbar for your Drupal users. It really isn’t going to do anything for what your visitors see, but your content creators, site administrators, and even site builders will see this as a much welcomed change. NavBar is first and foremost completely responsive, and for those of you who use the traditional Drupal administration toolbar on your mobile phone oh boy are you excited. The standard Drupal 7 install, not to mention Drupal 6, doesn’t offer the most mobile friendly administrative experience. NavBar helps resolve this. NavBar also offers a more flexible navigation option. You are able to use NavBar at the top of your site above the header, or as a sidebar on the left hand side. The customization of the tool, really helps set it apart.
Not only is the mobile experience improved, but there is a much cleaner and professional looking image presented than the Drupal 7 administration menu. Though this might not seem like much, for those of us who build Drupal sites for clients this is a big deal. Image is everything, and it is tough to sell Drupal’s out of the box usability against WordPresses out of the box usability. We have a lot of admin usability improvements in our standard Drupal installation to help combat this, but now NavBar is another one. Users almost expect clean and friendly design, and now they can get it.
I am not going to lie, NavBar in its current state is a bit of installation work, but most people should be able to figure it out if they have a little understanding for how Drupal is structured.
The first step for me is downloading and installing the project. I think that drush is the best tool for installing and enabling projects like this, but particularly for NavBar I suggest installing the project before moving to some of the other steps. The reason is that once the project is installed and enabled it will put some indicators on your /admin/reports/status page that can really help you troubleshoot in the next steps.
Once the NavBar module is enabled, you can visit the site’s status report using the path above and notice that there are a three statuses now associated with NavBar, and this is where the fun comes in. NavBar requires the installation of three libraries (Modernizr, Backbone, and Underscore), and you may have them already installed, or at least some of them. Using the status page at this point will help you find out if you have them already installed and ready to run, or whether you need to install them.
If you find that you need to install them, the process isn’t all that complicated, there are some helpful guides on the project page that will point you in the right direction. Or give us a shout we would be happy to help. Essentially it is a matter of downloading the libraries, or cloning their respective repositories, and moving them to your libraries folder in the Drupal installation. The Modernizr library requires you to follow a link and download a specific minimized version of the library but there are specific instructions to follow on the project page to help guide you here, so I won’t reinvent the wheel here. The instructions are pretty thorough, and relatively simple.
Once you have the libraries installed you can disable your regular administration toolbar and you are off and running. If you follow those steps and still aren’t having any luck, the site status report is the best place to look. Most likely it is an error with the libraries that were installed, and that report will point you to which library is causing trouble, and maybe even what the problem is.
We have fallen in love with NavBar, and it has started making a huge impact on our clients and how well they like using Drupal. We highly suggest you use it.For more tips like these, follow us on social media or subscribe for free to our RSS feed and newsletter. You can also contact us directly or request a consultation.