Setting up Apache on Ubuntu

To enable sites to be served locally on Ubuntu I needed to install a web server and the obvious choice is Apache. To install I used the apt-get command in the terminal window:

sudo apt-get apache2

This installs apache to the /etc/apache2 directory. To test the install, browse the http://localhost address in the browser. You should get a confirmation screen. Within the apache2 directory is the apache2.conf file, which contains all the config data for the web server to run.

I wanted to change the directory which Apache runs from, which is controlled the DocumentRoot setting, which has /var/www as the default directory. I changed this setting to point to /home/alex/www and put index.html into this directory to test that apache could find the file by browsing to localhost again. I just needed to restart apache for the DocumentRoot setting to take effect:

sudo /etc/init.d/apache reload

The one other thing to bear in mind is permissions. For apache to serve files in the www directory, the files need read permission setting for others.

Next steps on the Node.js/MongoDB adventure (introducing Sencha Touch 2)

My previous post described the long (at times arduous…) journey I took creating my first project with Node.js and MongoDB. The next project is to start building a map application based on the web app I built for artsfest 2011. The new app will do exactly the same and will use the same Sencha Touch framework for the UI, but will be totally different in the background using Node.js and MongoDB to feed the data.
Data

The first job is to work out the data requirements. For now I just need Markers and what I call Pois (Points Of Interest) which can be found at each Marker. In SQL world these would be two tables with the Marker ID as a Foreign Key in the Poi table, using a one to many relationship between Marker and Poi. In MongoDB world this would be two collections – all the examples I’ve seen so far use just one collection. This MongoDB tutorial suggests a starting point, using two collections (postings and users) and showing a reference between the two using the Simple Direct/Manual Linking method. So I think I will be creating two collections in a new database – Marker and Poi, with a Marker id being used as a reference in the Poi table.

To create the database is easy in the Mongo Shell

>use PoiPoi

Next is to create a collection, but rather than type it in I’d like to import from a file. This will enable me to use existing data and play about with the data until I’m happy with what I have.

To import data, first I prepared a json file to import, named “Marker.json”. This json contains the markers for my map. The most important thing here is to remove any whitespace, but configure it so that each new entry (document) starts a new line. Here is an excerpt of the file:

{ "MarkerID": 78, "title": "Birmingham Conservatoire", "long":"-1.905345", "lat": "52.479278", "icon": "artsfest.png", "description": "Home to classical music"}
{ "MarkerID": "37", "title": "Birmingham Museum and Art Gallery","long": "-1.903714","lat": "52.480173","icon": "artsfest.png","description": "The City's Art Gallery - the home of the PRB collection amongst other fine art works."}

from a new terminal window I then entered the following to import the data:

>mongoimport -d PoiPoi -c marker /home/alex/Mongo/Marker.json

To delete data from the collection execute the mongo command remove():

>db.marker.remove()

If you want to completely remove the collection then execute.

>db["marker"].drop()

Creating the Pois was a similar process. I just made sure each item had a “MarkerID” entry. I then imported the poi data using the mongoimport command.

Once I had both a marker and poi collection I could query them. What I wanted to do first is find all Pois with the same markerID, which could be done with the following command:


db.poi.find({"MarkerID":78})

Sencha

The next step is to build a basic sencha script to query the data and return a list of markers, then by clicking on a marker, it gives you a list of pois for that marker.

Back to Express

For this application I wanted to use Sencha and merge it with using Node.js somehow. I quickly realised that Express is the answer to this. Express can be used just to enable routes by using an instance:

var app = require('express').createServer();

app.get('/', function(req, res){
res.send('hello world');
});

app.listen(3000);

But you can also create a template application to work off by executing:


$ npm install -g express
$ express /tmp/foo && cd /tmp/foo

This will populate foo directory with subdirectories and files to get your app started. You can use the app straight away by executing:


$ node app.js


Coding the application

With the data and the application framework set up, I began writing the Sencha part of the app. The github home for the app is at https://github.com/lalexgraham/NodeSenchaMVC/ and has gone through 4 commits (and counting) already. I have found I have had to start off very basic. So a lot of the commits are nothing like the intended finished app, rather just basic apps to find out how to do certain things. In brief, this is what I have done so far

1st commit

For this commit I just wanted to set up the basic architecture of the site and get it reading data from MongoDB. So as usual with a node.js application, app.js at the root folder is the starting point. The Public directory contains the Sencha files, which includes the MVC folders: views, controllers, models, store. Running the app displays a list of the marker titles that are pulled through from MongoDB. I chose a list as this is the easiest way to display data pulled from a proxy but this has to be replaced by a map for the final version.

2nd commit

For the 2nd commit I got rid of the list and replaced it with a map. I then got a marker onto the map through the controllers/Map.js file.

3rd commit

Up until this commit I had been working with Sencha Touch 1.x….and then I noticed that Sencha Touch 2 beta is now avalailable. I thought that because I had only just started the app, I might as well write it using the latest version of Sencha Touch. So this commit was to start using Sencha Touch 2, going back to a basic application, just rendering “Hello World” and calling a view (/public/app/view/Viewport.js) that’s not fully implemented yet. The only part of the application code missing from this commit is the actual Sencha code library. This is basically the whole of the Sencha Touch 2 download put into a folder called Touch. This folder is huge but I haven’t figured out yet the minimum files I need. I have added a .gitignore file in the root of the app to ignore the Touch directory for Git and stop the repos getting bloated. The next job is to get the application back to how commit 2 looked using Sencha Touch 1.x.

4th Commit

Back to basics… Sencha Touch 2 has got me a bit flummoxed. I think I am trying to run before I can walk with using the new framework so this version has gone back to basics so I understand how views and switching between them works. To begin with I just want to show two views using the new MVC architecture that Sencha Touch 2 provides. I read up some more on the api and downloaded this helpful code example, and adapted it so there is just a Viewport which holds a welcome screen and a map,where you can switch between the two using icons on a toolbar. My next post will describe the basics of this application and how I understand it.

5th Commit

I have centred the map, or at least tried to. There appears to be something wrong in how Sencha Touch interprets Google lat lng coords. i wanted to centre the map on Birmingham city centre, but its more like Northampton. I have successfully added a controller which puts a marker on the map in the intended location – New Street station in Birmingham city centre.

6th Commit Mar 11, 2012

This commit plotted markers stored in a MongoDB collection onto the map. There were two events I wanted to ensure had happened before I plotted the markers. Firstly that the map had rendered and secondly that the store of markers had loaded. I struggled with the right method to do this. I didn’t want to do the plotting within the map view itself or the store for the markers as events, as I understand, should be in controllers. I eventually got the Marker controller (app/controller/Marker.js) to listen for both events. A quick explanation is that the refs and control configuration gets a reference to the Map and reacts to the maprender event by calling putmarkers function. Within this function, a ref for the store is obtained by calling Ext.getStore(). I just noticed I got a reference to the store in the init method as well, which I couldn’t use in putMarkers as it was out of scope. The Each reference created in the refs configuration produces a Setter and Getter method automatically, so this.getMap() gets the reference to the map. A callback function waiting for the store to load ensures the markers are then plotted only when the store has finished loading. The controller took a long time to write and I eventually had to post a question to the sencha forums. The response, from the helpful but concise (guess he needs to be) Mitchell Simeons. The getStore() method got me what I needed. I have learnt the following from this commit:

– If something doesn’t work, go back to basics. I created the marker list to do exactly that when the plotting of markers on the map didn’t work. By doing this I noticed I had a typo in the model, so the store was loading but the data model didn’t render correctly.

– The iconCls which puts the icon image onto the toolbar is limited to those listed under @if $include-default-icons in /home/alex/NodeProjects/NodeSenchaMVC/public/touch/resources/themes/stylesheets/sencha-touch/default/widgets/_buttons.scss . So ‘map’ works but not ‘list’.

So now I have the app reading from and plotting markers from MongoDB. The next step is to complete the application as much as I can before adding localStorage. I may use backbone as well for the admin side of adding editing markers.

7th Commit Apr 7, 2012

This commit took a long time to get to as I had to rethink the whole approach in terms of the views to get to the sequence I wanted. This commit achieves the basic requirement of the app and the sequence I wanted – start from a map, click on marker, show events (items) located at that marker and click on an event (item) to view more detail, reading from the two stores of data (markers and Pois). With the tabBar I didn’t want all the views to appear on the tabBar and I couldn’t quite figure out how to setup this drill down of navigation and have relevant back buttons appearing. For example I couldn’t get setActiveItem working to put the relevant view into the viewport. Using nelstrom’s Presidents example, I found ext.navigation.View, which is an excellent way to utilize a drill down navigation as opposed to the tabBar where all the views are on the tabBar, unless you customize it.

So with Ext.navigation.View, I could push the relevant view into this containing view using events in the Main controller. When pushing the view, a back button appears automatically to pop the view off from the Ext.navigation.View. Very neat.

Apart from a few minor tweaks there is one thing I still need to fix and this I think show my limitations in terms of fully understanding the whole Sencha framework and referencing instances of classes:

I couldn’t reference the title attribute in Poi.view.List from the controller Main. I tried to do this in the showList function. So far I have been referencing views in the refs part of the controller config using their xtypes (Stores are easier as they can be referenced using the getStore function)… I couldn’t reference the instance(s) of Poi.view.List in the refs however as from what I understood of the flow, no instances are there to reference when the app is instantiated which is when, presumably, the refs in the controller do their job.
So from the Presidents example, I found how to reference in the control part of the controller by again using the xtype then the event you want to react to. As well as the disclose event (to show the detailCard) I thought I could use the initialize event to alter the title of the list. Looking at the Sencha Docs, I could see that the first argument you can pass in to this event is the instance of the list component. So I use this reference in the showList function. console.log(list) returns something, but still cannot set the Title. …? So there is something I am missing here.

8th/9th Commit May 16th

This is my final commit for this project. I won’t add more waffle to this post but just to clear up my last problem to assign the title to the list view I used:

main.push({
xtype: 'listCard',
title:item.get('title')
});

This set the title when I pushed the listCard onto the ext.navigation.view.