How to Build a Trello clone with Commenting and Fauna.
Tags: database, fauna, programming, beginners
Published: 2021-04-16 05:03:00



Simple to-do lists are great for keeping track of tasks you need to make come to reality but if you’re working with a team where tasks have sub-tasks that have sub-sub-tasks and more, that’s where you especially need a project management software. 

Project management apps, even simple ones like Trello, can break your project down into achievable steps and give your team a more easy workflows. 

#Overview 

This tutorial shows how to write a Trello-like ticketing system from scratch to help you build a similar project management tool on your own.

At every step, we will consider the minimal viable product requirements and implement them.

The stack we will use is the **AngularJS**, **Node.js** and **Fauna**. Now that I’ve given you the overview of how the tutorials will go. Let’s get in: 

Now, let’s choose: 

- no users, no collaboration

- a single boards with lists and tickets
 

Let’s set up a board view that allows users to add lists and tickets. For that, we will define a page in Angular:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgknryf4nptdo6nity1a.jpg)

Then we will define the controller with some mock data we can display: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2e58rmxbhdzizvtekqb.jpg)

As you can see, I chose a very naive data model with the following traits:

- Each ticket has a title.

- Each list has a name and its tickets.

I have an array of lists. While this model might change in the future, it is too early for me to consider anything more complex. 

When I think about the first functionality I would like to add ­ which is CRUD (Create, Read, Update, Delete) for lists and tickets. 

When I think about the first functionality, I would like to add something that’s known as CRUD (Create, Read, Update, Delete) for lists and tickets. I am convinced this model is sufficient, so let’s move on.

For starters, we’d want to see everything is wired correctly. So I will start with a simple page:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69974zkfc4zllk41cgds.jpg)

To verify everything is fine, simply run npm start. Thanks to the awesome simple Node.js setup, the browser should open. But alas, the text does not appear. So let’s troubleshoot it.
Yippe, we are done with that part. Now, Let’s define a default route.

The board route specifies a **/board** page, but the browser opened on /**index.html**file. I can manually write /**index.html#/board** or simply add a default route. I prefer the latter and so we can write:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ojpzxhe9obqg7fnp5xt.jpg)

Also, let’s include a .js file

You can see the blue background color, but still no tickets. When you open the console and see an Error with the message **Argument'BoardPageCtrl'is not a function, got undefined**
When you add a log print **console.log('initializing controller')** at the top of the page, you should see that the code is not invoked.

Now that we made sure everything is wired correctly, we can move on to painting the tickets. I start the HTML by adding a div with ID matching the page’s name. This is a habit of mine as some of the CSS will be specific to this page. Also, let’s include a .js file.

You can see the blue background color, but still no tickets. When you open the console and see an Error with the message **Argument'BoardPageCtrl'**is not a function, got undefined.
When you add a log print console.log('initializing controller') at the top of the page, you should see that the code is not invoked.
Now that we made sure everything is wired correctly, we can move on to painting the tickets.

I start the HTML by adding a div with ID matching the page’s name. This is a habit of mine as some of the CSS will be specific to this page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wg01ex2wcw9s46b50h7f.jpg)

Now I would like to display a list and enable changing its name.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5cy64t1jpyv7wetab535.jpg)

Next, we would like to paint the tickets for each list.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8ibljzuw00yb2bflyg2.jpg)

Last but not least, I want to add a button with the label **Add Ticket**.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cj9wzmsotzmzr5q20e8.jpg)

The final HTML looks like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2ygj0c59hfdr6munpb2.jpg)

So far, everything looks awful. So it’s time to add some style.
To keep the project organized, let’s create a file named **_board_page.scss** (notice the naming convention I keep) and I start it with the page’s ID.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55nyzw6ufdbph073slwo.jpg)

Let’s start by adding the board’s background color:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfihcllrzborlb38dlv4.jpg)

Now, let’s make the background to not be all over the page.  You could use **width: 100%**and **height: 100%**, but that has some other implications we want like to avoid. So instead, let’s use **absolutepositioning**. 

It will also resolve some scrolling issues down the road.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vslex0lsyw0j9gr6qsx5.jpg)

Next, let’s make the lists horizontal — one next to the other.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ol8ntcoyzu79y4vwpt9.jpg)

Now, let’s display the title properly and add background to the lists with some spacing:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8p32ohtf4s44kdpfdzsj.jpg)

Let’s also add padding on the **#boardpage** with **padding:20px;**

Note that I used **margin-left** to have spacing between the lists, but when I wanted spacing from the page, I added padding on the page.

I could have added **margin-top** on the lists and **margin-left** on the left-child to achieve the same thing.

Saying that, this is what the app should look like at this point: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7iabhsheigpv88i2rpmn.jpg)

Now let’s style the button:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cd9edgaycv0ns00m7of.jpg)

Let’s add some style to each ticket:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qq2etfy66m71iog7tnqo.jpg)

So paying attention to small details and acquiring good practices with CSS will save you a lot of time down the road.
If you are not seeing the style changes, make sure you remembered to add an **@import 'board_page'**; statement to **main.scss**

##Adding list and ticket functionality
It’s time to enable adding tickets and lists. We already have a hook for adding a ticket on the Add Ticket button but we also need some action to add a list. For now, binding it to double­-click on the board sounds nice.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0bwz9pvkbufol40qiwd.jpg)

And in the controller, we will implement these functions:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs57h62ov2fu8bssso3v.jpg)

When I click ‘Add Ticket’ repeatedly, I see the lists spills over the content area.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0103jj8rtog0o29mqjeh.jpg)

To quickly fix this, add the following css
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83iom9ftr0ja4adhj3gx.jpg)

So far, we have some pretty fair results. But Trello is very famous for its drag & drop ease and it would be a shame not to have it.

Luckily, there’s a pretty nifty Angular library called angular-drag­-and­-drop-lists, so I quickly add it by running bower **install­ -S angular -­drag-­and-drop­lists**. I also add a module dependency and the relevant JavaScript file to **index.html**
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfotrpx5x9i0w0xnnl9w.jpg)

Following its instructions, let’s add some dnd attributes to the ticket **div**
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6xh8roaos9pehruvabn.jpg)

And then I eagerly go to verify if it works — and it does! But it’s ugly… So add the following style:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylwjt30mppo045bqr2i6.jpg)

This is much better, but still, something is not smooth enough when we try to move a ticket to the bottom. The reason is that there is not enough space between the list body and the button, a quick solution is by adding:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0krfnealb13wrp6ctf2.jpg)

All the code above gets us to some promising initial results:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc4nrqfvdymcb1g0jfya.jpg)

#Modelling with Fauna

Today, a software system might use a relational database for transactional data, a graph database for social identity management, and a time series database for analytics, all within the same application.

To address this issue, some databases attempt to offer a multi-model approach. These databases offer multiple modeling techniques (e.g. relational, document, graph, etc.). within the same database. 

However, these systems introduce model-specific interfaces that are often distinct, and cannot be used in combination. They prevent data from being accessed using the right approach at the right time.

FaunaDB takes a different approach to this problem. The Fauna uses a multi-model approach that unifies the ability to read and write documents, with the ability to use relational, graph and other styles of data interactions within the same query language, giving developers flexibility to choose the right approach in context.
Database models have evolved over time. Let’s examine some of the current approaches available in the market.

Fauna offers the following database system: 

##The Relational Model

Databases built on the relational model are able to evolve with their application over time, at the cost of modeling the shape of the data in a schema.

Imagine you are building a social media app where users can post content and follow other users. The main screen of the app is the recent content from everyone the user follows.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxsmn4roiysio0f7t3h8.jpg)

##The Document Model

In the document model, data can be stored with any structure. Typically, it is stored as it is received or presented, for ease of development. Each document is independent, with no joins, constraints, or relations between documents.

The biggest advantage of a document database is the flexibility to store data as it comes without configuring a schema first.
In our social media example, a document database would cope just fine with having different types of content to publish. Where it gets challenging is creating the individualized activity feeds. 

Without support for joins or complex queries, application developers resort to stitching together the results of fan-out queries in code, adding delay and complexity to each page view. An alternative is precaching the timeline view by writing new content to it as it is published.

##The Graph Model

The graph model is useful for finding patterns in relationships. If you’re optimizing container shipping it helps to be able to compare potential container routes on attributes like cost and speed, for instance in preparing for regulatory changes or in case of disruption to major shipping routes.

Graph APIs in the same context as operational and transactional data are sufficient for many use cases, even without specialized graph storage and processing.

The graph model is typically implemented to optimize fast searches, not scalability. Specialized graph databases rely on scale up infrastructure utilizing a single server with large amounts of memory to make processing large data sets feasible.

##The Temporal Model
Enterprise applications need to track changes, and social applications need to present the latest updates from friends. All sorts of applications can benefit from auto-expiring records, especially with requirements like the GDPR becoming common.

Event and snapshot feeds can also be useful for updating external indexers and other integration tasks.

Implementing temporality in relational databases requires adding additional dimensions to your schema to track valid time and transaction time for each record. Recovering from mistakes, auditing change history, and querying old versions of the data are supported natively by FaunaDB’s temporal snapshot storage.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1sz6lddiftjywlyx9go.jpg)

#Conclusion 

Choosing a database with a unified query model like FaunaDB allows you start with the relaxed constraints of the document model, but add relational constraints and graph queries as necessary. 

The freedom to adapt your query model to changing requirements gives you a solid foundation for the future of your organization's data.

So, with this. I think you have learnt from this tutorial how to build a simple trello clone, commenting and also learnt modelling with Fauna.