Long time no blog, because I prefer to blog about stuff that I finished. However my current fsharp / Websharper project takes some time, and because of working conditions (little time to spend) it will take even quite some more time. So let’s write something about unfinished business.I work at a contractor company, and we have the process that every employee needs to submit their time spend in a timesheet at the end of the week and month. And then the invoice process works based on this information. The Timesheet is one of those “internal projects”. However we’ve been doing well the past years. And one of the side-effects that even FP cannot solve is, that we currently have a very old Timesheet application, and we need a new one. The old one is written in Asp.Net, where every click runs code-behind.So we created a combined goal. A new Timesheet is a perfect way to gain some serious experience with Websharper, bringing knowledge into the company, and providing co-developers with some example code. I’ve registered the time spend in the old timesheet (haha), and since the start of februari 2015 until now (june 2015) I spend a little less than 100 hours on this project. Which is two-and-a-half weeks in normal working hours. And this includes learning, researching, fighting source control, and coding.As you can see from the screenshot, I am a better web-developer than a web-designer. We have a pixel-fairy at the company, so this user-experience is not final.

My very first step was to create a Single Page Application, which created a grid in static HTML. Just to get a feel with Websharper, how the framework works, how you use the markup elements and so on.

The control at the bottom of the screenshot made me look at Websharper.UI.Next. If you press “submit” after entering your data and there is some connection problem, then you’ve lost all that work. For simple weeks no problem, redo it later. But if you do many different things and it takes a lot of time to register your activities, then lost work is very annoying.Therefore, the control at the bottom is used to store the contents of the timesheet locally, using local storage in the browser. It stores the data from the grid for one week. You can store multiple weeks, making a list of stored weeks. If you click an entry in the list, the stored data will appear in the grid. You can also delete from the list. In other words, that list is dynamic, which is why I used Websharper.UI.Next to implement this. That choice made the implementation very easy.This got me started, and finally I rewrote a lot of stuff into Websharper.UI.Next, including the grid itself. The simple reason is that task-codes may be different per week, so if the user selects a different week, then the grid needs to be redrawn based on the data, the column and row headings. Rewriting the grid into Websharper.UI.Next was a little harder, compared to the static way I started with.

The hardest part was, wiring events. With Websharper.Html.Client, you can create a Button control, and add event “OnClick” later. With Websharper.UI.Next, you add an event in the same step as you create the control. That became a challenge when I wanted to add keyboard navigation to the grid with the cursor keys. That requires an algorithm about where you are, and where you want to go; that information is missing if you haven’t created source and target yet. The solution was to give every element an id, based on grid coordinate, and in the OnKeyDown event handler use “getElementById” from Javascript.Even though Websharper.UI.Next could scour some rough edges, it is still awesome. It really helped me to follow the well-known MVVM pattern.The application data-model was created using Reactive Var’s. This data-model is stored somewhere at a central place, and communicated to all the Widgets in the application.So via the Calendar Widget, you can select a week. The data for the week is recovered from the Server (which makes a call to a Dynamics NAV backend system). And when the data of the selected week arrives at the client, you write it into the data-model, and it automatically appears in the grid. Same goes for the LocalStorage Widget. When you select an entry in the list, the data is retrieved from LocalStorage, and written to the data-model, and it automatically appears in the grid.What I also like very much in Websharper is that you can do both client and server code in one sourcefile. You don’t have to do code behind. It is good to use this with care though. If the server-side code was too many lines, or shared between different client-side locations, I usually decided to store the server-side code in a different file. It is a choice between grouping and focus, and I prefer focus. A developer spends most of his/her time on searching (for a bug, or good location to insert new code), so that’s the process I want to make as easy as possible.Later this month I will be holding a presentation at my company about this project. And from then on we will decide about its future.