One AIR annoyance

So this is a minor nit - I really do love AIR, but I've noticed something funny. I go to install an application - one that I've installed before, and the installer tells me:

Ok, no big deal, I'll just move the old file or pick another file, but nope, you can't do that, because the installer dies right there! Why not let the user go back and correct the install folder? Or move the file? Sure it takes me all of 5 seconds to do this and rerun the installer, but I wish it wouldn't abort the process because of a simple problem like that.

Ok, so this isn't a complaint just about AIR - I've seen other applications do this as well, but I figured that if I complain about it, maybe someone will point out that I simply created my installer wrong.

TimeTracker updated (again!)

Well I'm done. Mostly anyway. I set out when creating this application to get more familiar with SQLite, and I've certainly done that. Today I think the TimeTracker application is finally complete. A lot of folks helped out with it so I definitely can't take all (or most) of the credit.

In this final build I added a few more features, including, the CSV export, which was pretty fun to build. Creating the CSV string was trivial. I even went the extra step and had the string properly handle data with commas and quotes.

To save the file, I used this excellent article by Mike Chambers. It's pretty trivial actually to ask a user to pick a file and then save the data. AIR really does make this simple.

I also added some basic validation to the forms in the application to make it a bit more stable.

I will warn folks though - I wrote this to learn, and I wrote it as I needed a way to track hours. But frankly, I wouldn't trust my code. If you want to really use it, I beg you to use the CSV export feature to make backups. I don't want to be responsible for someone losing all their data.

It was also suggested that I put this application up on RIAForge. As I have an "in" with the manager, I was able to get the project approved pretty quickly. You can download both the AIR file and source here:

http://timetrackerair.riaforge.org/

Now on to my next AIR project.

TimeTracker Updated - Dealing with long strings in Flex DataGrids

I've updated TimeTracker again. This version includes the code fixes by Sid Wing (thanks!) which was part cleanup and a fix to the mx:Legend. I agree with Sid's comment that the docs could certainly be clearer.

I also removed the 'Enter key submits hours' thing so folks could enter multiline task descriptions. This is where I ran into an issue with the Flex DataGrid. It refused to correctly render the text in a readable format. Thanks to Scott Stroz for pointing out the variableRowHeight attribute for Flex DataGrids.

<mx:DataGrid id="todayshours" dataProvider="{todaysHoursData}" width="100%" height="100%" sortableColumns="true" variableRowHeight="true">

Oh my sweet little adorable Flex DataGrid, is there anything you cannot do?

I also added word wrap to the description columns as well as sorting. (Although I bet date sorting isn't quite right.)

Next up is the CSV export. After that is done I plan on releasing the code to RIAForge since there seems to be some interest.

Time Tracker AIR Application Updated

I spent my lunch time today working more on my Time Tracker application. I added 2 new tabs. The first is an Hour Log tab that lets you see all your hours, not just the ones for today, and you can do filters by client, projects, dates, or descriptions.

The date filter was pretty interesting. SQLite has a julianday function that returns the number of days since some date in the past (I don't have the docs in front of me, let's just say it was a really, really long time ago). So to do a date comparison you can use the julianday function to compare the date in the database with what you want to filter by.

The next tab I added is a basic Stats tab, which right now uses a Flex Pie Chart to show you the total number of hours spent on projects. One tip - you won't find the docs for charting in the main developer's guide for Flex 3. Instead, go to the docs page and download Adobe Flex 3 Data Visualization Developer Guide. The description focuses on advanced stuff, but the guide also covers basic charts. Not sure if there is a difference, but it is the guide to use.

So in general, the charts are super easy to use - however, mx:Legend refuses to work for me. Check out this screen shot:

See the 3 black squares? The legend tag is smart enough to know I had 3 pie items, but refused to actually show the labels. The docs say I need to use nameField in my series (although what I really want is the labelFunction!), but even though I did that it refused to show anything. I know it's partially working because when I change the filters to result in 2 pie wedges, my legend changes as well, but I still just get little unhappy black squares (which will be the next new band to come out of London, mark my words).

Anyway - I think this is it for now. I just want to add one more feature, and that's a CSV download from the Hours Log, but after that the application will be done.

TimeTracker Updated, and how I did date filtering in SQLite/AIR

Sometime ago I began work on a simple AIR tool to help me record my hours. It's been a while since I worked on it, but this weekend I decided to take another look at a nagging issue that I had never resolved. How do I do date filters in SQLite? Specifically, the "Enter Hours" screen should only show the hours you entered for today. (I plan on adding a Reports tab later to let you browse hours and generate reports.)

I worked and worked and worked on this issue before, but figured a fresh look may help. I finally got it working. I used the strftime function, which is really meant to format dates, but I was able to use it in the WHERE clause as well. This is the final code I ended up with:

hourDataStatement.text = 'select hours.description, hours.hours, hours.date, projects.name as project, clients.name as client from hours, projects, clients where hours.projectidfk = projects.id and projects.clientidfk = clients.id ' +
      'and strftime("%d",date) = strftime("%d",date("now")) ' +
      'and strftime("%m",date) = strftime("%m",date("now")) ' +
      'and strftime("%Y",date) = strftime("%Y",date("now")) ' +
      'order by date desc';

In case that doesn't make sense, what I've done is added where clauses that do:

where 'format the date to show just day == the day of today' AND 'format the date to show just the month == the month of today' AND 'format the date to show just the year == the year of today'

Not incredibly elegant, but it worked!

During my testing I also ran into another issue. One thing I tell people about Flex development is - it is incredibly easy for the most part. All you have to do is get comfortable with the tag set and have an idea of what you can do in ActionScript. What is difficult is getting used to asynchronous operations. The idea that - I can run some remote function but I have to write a function to handle the result. Maybe it's just me, but time and time again this trips me up.

The problem I ran yesterday involved the start up code for the application. I had deleted my old database so everything was run fresh. I got an error stating that the schema had changed. I think I know why. My old code did this:

  • Open an async connection, when open, run SetUp()
  • SetUp would create new tables if necessary
  • Setup used a Synch connection.
  • When done, continue on the app
  • The rest of the app used the original asynch connection.

So my take on the bug was - the original async connection got "confused" when the db was changed underneath it. I edited my code a bit so as we now do:

  • Open synch connection and make tables.
  • When done, open the new asynch connection.

And this corrected the problem. I've included both the source and the AIR installer for the latest version. Now I'm very happy as I get to play with charts and generating reports!

Adobe Developer Week

Wow, I just found this out myself, but it may be old news. Next week Adobe is hosting a week full of developer sessions you can attend via Connect.

Adobe Developer Week 2008

Topics cover ColdFusion, AIR, Flex, Flash, and other items. If you can't sign up for a session (or be there when it happens), Adobe will be providing recordings 5 days later.

Again - wow!

AIR Support?

And with the final release of AIR, cue the puns. Ok, seriously, I must have some kind of mental block with Adobe's web site. Where does one download documentation for AIR? I did find the online docs, but I had to use the site search tool to find it. I've yet to find a direct path to them.

Developing AIR Applications with HTML and Ajax
Developing AIR Applications with Flex
Developing AIR Applications with Flash

I haven't yet found the PDF downloadable version. Can someone share? I'll also use the Adobe web contact because I can't believe I'm the only one wondering the documentation link is.

Flex 3, AIR Released

The title says it all - and just about every other blog out there. Adobe has released both the third edition of Flex, as well as the very cool AIR. My readers know how I feel about these products, so I won't say much now (and plus I want to go to bed ;), but get downloading!

Time Tracker AIR Update, and what I learned about label functions and optional args in Flex

I've got a big update to the my little Time Tracker AIR application, thanks mostly to Kyle Hayes. He gave some UI loving to the app - see below:

I've done a bit more cleanup. One of the things I fixed was my duplicate labelFormatter. The labelFunction feature is one of the neatest things in Flex. When it comes to a control that takes a set of data, you can say, "When displaying X, call this function." Your function can then do stuff like, "If the row of data has a price more than 100, mark it (Expensive!)". You get the idea. What was bugging me though was that I wanted to use the same labelFunction for my DataGrid and my ComboBox. But the DataGrid passes 2 arguments to it's label function, and the ComboBox passes one. I wrote two functions which both did the exact same thing. Turns out (and I found this online but forgot to bookmark where) there is a simpler solution - just mark the section argument as optional. Here is an example from my code:

private function projectLabel(item:Object,col:DataGridColumn=null):String {
   return item.project + " (" + item.client + ")";
}

In this code block, the second column has an optional value. It is optional because we define a default value to use in case one isn't passed.

Anyway, most of my changes are pretty small. I switched to using States to handle "loading" versus 'real' application. I also made the Hour panel notice if you have no active projects. (Need to double check that I have the active flag in there.)

I'm still struggling with the dates though, and I've had some folks help me out on my other post, so hopefully that will get corrected soon.

So now I'm going to turn my attention to a reports page. I've only played with Flex charts a bit, but I'm looking forward to it. I'd especially love to be able to find out which client/project paid me the most money, something that isn't possible with the current system I use.

I know I keep saying the following, but I should repeat it anyway. I'm really loving AIR and Flex. But please consider my code to be anything but best practice.

Two SQLite tool recommendations

In regards to my post yesterday on AIR and SQLite I thought I'd share two tools that can help developers.

I've been using a cool AIR based SQLite tool from Christophe Coenraets. You can find it here. It works rather nicely and I like that it has a 'history' feature since I always have trouble finding the exact location AIR stores my DB file. (I typically trace the nativepath of my File object when I forget.)

Then a commenter named Gareth pointed out that you can find a Firefox plugin as well. (About the only thing you can't do in a Firefox plugin is peace in the Middle East.) I installed the SQLite Manager today and it runs pretty well.

I'm not sure which tool I'll give preference too, and I'm sure there are others as well.

And lastly, if any AIR/SQLite experts out there want to help me with my date problem, let me know.

More Entries