Thursday, July 29, 2010

Fun stuff with JQuery

Well, I've just about got to the stage where the data is being sucked out of the project XML file and into the database - and I'll add more detail about that when I have tidied it. However, in the meantime I thought I'd put a bit in here about the planned presentation.

The idea is to graph the resources' usage over a given time period. A guideline would be used to indicate whether the resources are over or under allocated.
The solution I had in mind was to use <div> tags of solid colour with a height varied to the height of the column in graph, dependent on the resource usage for that time period.
And to do this, the brave world of JQuery.

To begin with, I wanted to see if I could vary the height of a div tag using a text value input into a form on the page. Here is the code:
<script type="text/javascript" src="/Scripts/jquery-1.4.1.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#setHeight").click(function () {
$("#variable").height(parseInt($("#height").val()));
});
});
</script>

For a half-decent overview of JQuery, check this:

Let's break this down. The first line
<script type="text/javascript" src="/Scripts/jquery-1.4.1.js"></script>
is used to make the JScript functions available to the rest of the page.

$(document).ready(function () {
This is the line that ensures the HTML DOM is fully loaded. It stops code trying to work with objects that are not yet rendered.

$("#setHeight").click(function () {
When the button (not relevant) of id="setHeight" (very relevant) is clicked, carry out the instructions...

$("#variable").height(parseInt($("#height").val()));
Bit more complicated, but not much. For the item (the div) with id="variable", update the height to the value in the text box with id="height". The parseInt is required to cast the string returned to an integer value. I'm always surprised when Javascript, a language that isn't strongly typed, doesn't do this kind of thing for you.

For reference, the HTML elements in play here were:
<input type="text" id="height" />
<input type="button" id="setHeight" value="Set Height"/>
<div id="variable" style="background-color:Red; border:2; height:100px; width:100px">


Tuesday, July 27, 2010

'Steam'lining the upload

Afternoon,

Turns out yesterday's approach to get the uploaded XML file into the XmlDocument object was a bad idea, which doesn't come as a surprise. It was simply the only way I could make it work at the time.
However, the XmlDocument.Load operation had not completed before I tried to delete the XML file from disk causing conflict errors. As this was the smallest possible MS Project XML file, this was clearly a non-starter.

I've returned to the original idea of reading the file straight into the XmlDocument object from the Request.Files[x].InputStream. Which I didn't know existed yesterday...

Here is the new code for the method:

HttpPost, ActionName("AddProjectPlan")] //don't really understand this?

public void Add()

{

foreach (string file in Request.Files) //only posting one element from the form, but this would work for many

{

HttpPostedFileBase postedFile = Request.Files[file] as HttpPostedFileBase;

if (postedFile.ContentLength > 0) //if file not empty

{

//create an XML object for loading in the project plan xml

XmlDocument xmlProjPlan = new XmlDocument();

try

{

xmlProjPlan.Load(postedFile.InputStream);

Response.Write("File " + postedFile.FileName + " successfully loaded
"
);

}

catch

{

Response.Write("File " + postedFile.FileName + " is not valid XML
"
);

}

//Response.Write(xmlProjPlan.InnerXml); //for debugging

}

else

{

// Let user know there was a problem

Response.Write("No file submitted or file zero length");

}

}

}

}



The problem was solved by some good people at StackOverflow, question and answer here:

Monday, July 26, 2010

ASP.net MVC file upload

Today's task was simply: upload a file from the local machine and save it out to the 'webserver'.

To do this I created a new controller HomeController.cs and a new View, Home\Index.aspx

The important bit of Home\Index.aspx looked like this:
  <form action="/Home/AddProjectPlan" method="post" enctype="multipart/form-data">
         <label for="file">Filename:</label>
         <input type="file" name="file" id="file" />
       <input type="submit" name="submit" value="Submit" />
     </form>


To HomeController.cs I added the System.IO namespace, and the following method:

[HttpPost, ActionName("AddProjectPlan")] //don't really understand this?
public void Add()
{
foreach (string file in Request.Files) //only posting one element from the form, but this would work for many
{
HttpPostedFileBase postedFile = Request.Files[file] as HttpPostedFileBase;

if (postedFile.ContentLength > 0) //if file not empty
{
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "temp\\", Path.GetFileName(postedFile.FileName));
postedFile.SaveAs(savedFileName);

// Let user know that it all worked and where the file was saved
Response.Write("File submitted to " + savedFileName);
}
else
{
// Let user know there was a problem
Response.Write("No file submitted or file zero length");
}
}
}

There are a few things in there I don't 100% understand, particularly what the [HttpPost,...] notation at the top means. I tried adding this all into a separate method AddProjectPlan, but for some reason the form post couldn't find this. If anyone has any ideas or decent tutorials, please let me know.

Useful links
While doing this work I found the following very useful:

(and less so)

A Start

Hello,

Day one on the new software development project, ABLE. The plan is to create a suite of quality, low cost, enterprise level project management software - and have a lot of fun while doing it. As a contract Project Manager I'm pretty confident I know the market, as an ex-coder I'm pretty rusty and very out of date.

This blog is initially about the development of the software and the useful online resources I've used to to help me get back up to speed. Some community involvement through this blog would be excellent if you feel like chipping in.

Right, an overview:

Product Summary
In the first instance I plan to develop a thin vertical slice of end to end functionality that allows multiple Microsoft Project Plans to be loaded in to a web interface, and then display the resource utilisation over different time-frames (e.g. days, weeks, months) in a graph format. For v1 support will only be MS Project files saved as XML.
This solves the problem that most mid sized organisations do not want to purchase MS Project Server and this resource view functionality is very useful at a strategic level.
From an ABLE point of view, this implements a lot of code that can be built on for future 'vertical slices' that will extend functionality.

Technology choice
My background is MS, so I've gone for a C# ASP.NET MVC implementation. As I'm using the free Microsoft Visual Web Developer 2010 Express, I've currently opted for xUnit.net for my unit testing. However, I think it will be a while before that gets implemented as I have a few more basic functionality issues to solve first...


If anyone has any comments or suggestions then I'd love to hear about them. I'm doing this as much for fun of coding as any serious attempt (yet) to make a career, so the geekier the better. I'm not keen to hear the 'there's x product that already does this' - I know there's a lot of stuff out there, but see above comment about doing this for fun ;-)

Thanks,

Jonathan