Build a Bug tracker app using ToolJet and Appwrite.
Published: 2022-05-05 20:12:29

This article will see a complete guide to building a **Bug-Tracker** app that allows you to **create** and **manage** your bugs with title, description, project name, priority, and tag with inbuilt messages to notify the user. You can preview the hosted app [here](https://app.tooljet.com/applications/5d313681-ff87-4e50-adb9-6e4c6c128f6b)

We are going to build this app with three simple steps:

1. **Building the UI**
2. **Integrating data sources and creating queries**
3. **Connecting event handlers**

Here’s how our app will look in the end:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl8ajrgcikjymjy8oi5d.png)
 
Pre-requisite:

1. **ToolJet**: Building the UI of our app
2. **Appwrite**: For storing bug reports in the Appwrite collection
3. **Aws S3**: For storing images in the S3 bucket
4. **DigitalOcean**:  For deploying Appwrite

This tutorial will help you build the complete app in minutes, and it will allow you to understand various steps with a full description. It would be best if you go through the following articles before we start building an app. Let's buckle up for a fun developing experience.


1. [Tooljet](https://www.tooljet.com/)
2. [Appwrite](https://marketplace.digitalocean.com/apps/appwrite)
3. [AWS](https://docs.tooljet.com/docs/data-sources/s3/)



## Building the UI

First, let's start with building the UI for our app. Open ToolJet on a new tab and click “**Create New Application**”. We will require the following widgets to make our entire app. 

1. Container
2. TextInput and TextArea
3. Button
4. Table
5. Dropdown
6. File-Picker
7. Image
8. Modals

**Step 1: Create a table view to list and manage the bugs**

Drag and drop a **container** widget from our widget menu on the right, and expand it completely. Now drop the **table** widget inside our container. Once done, Let's inspect the table widget and start adding the following:

1. **Add column**: Title, Description, Priority, Status, Project Assigned & Message

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf2tmsr209fn73pol9n5.png)

2. **Actions Button**: “View details” and “Edit.”  We can style our buttons by clicking on the actions. We will later set the “**Add Handler**” property once we finish our modal views.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3w2fud53hjtxv8v525pe.png)
 
On the top of the table, add the “**Text**” widget called Bug Tracker and a “**Button**” widget with CTA “**New Bug**”. We can style the button by adding colors and border radius to it. We will set the **onClick** event later. 



**Step 2: Create modals for CRUD operations**

We have to create three **modals** popping up to perform all the crud operations in the app.  You are **free** to make your layouts.

1. New Bug: This allows you to list a new **project-specific** bug with titles, descriptions, priority, messages, and related images.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6cndyn9a7hf9xsd8eb7i.png)

Drag and drop texts, text-input, text-area, dropdowns, file-picker, and button widgets and adjust according to the UI above.

Inspect each input field and add a label, placeholder, and add the option **values** and **labels** in respective drop-downs with the following inputs. You can modify these values as per you 

a) **Select priority** : `{{["Low", "Medium", "High"]}}`
b) **Name of Project** : `{{["Mobile App", "Internal Tool", "Website"]}}`
c) **Notify Message** : `{{["Resolve Now","Resolve in 3hrs", "Resolve within 48hrs", "Thanks for resolving"]}}`


2. **View details**: This allows you to watch specific details around your bug for a better understanding.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yr85isffmi1z4rc3dut6.png)

Drag and drop texts and image widgets to adjust according to the UI above. We display the bug title, priority, description, message, and images.

Inspect modal, set the title to Title:`{{components.table1.selectedRow.title}}` 


We need to bind the data in our texts to display the following UI.
a)  **Message**: `{{components.table1.selectedRow.message}}`
b)  **Priority**: `{{components.table1.selectedRow.priority}}`
c)  **Project**: `{{components.table1.selectedRow.project_assigned}}`
d)  **Description**: `{{components.table1.selectedRow.description}}`

Inspect the image widget and set the URL to:  `{{queries.ListDocument.data.documents[components.table1.selectedRowId].preview_url}}`

e)  **Message**: `{{components.table1.selectedRow.message}}`


 
**3. Edit:**  This allows you to perform edit and delete operations on an existing bug.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u96ghltcm53ypa6zdqrp.png)

Drag and drop texts, text-input, text-area, dropdowns, file-picker, and button widgets and adjust according to the UI above. Currently, we don't have an option to edit the image. I will release it in the next version of this application.

Follow step one to populate the dropdown option's value and label. Now add the default value under each input field as:

a) **Title**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].title}}`
b) **Description**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].description}}`
c) **Priority**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].Priority}}`
d) **Name of project**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].project_assigned}}`
e) **Notify Message**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].message}}`
f) **Uploaded Screenshot**: `{{queries.ListDocument.data.documents[components.table1.selectedRowId].preview_url}}`



**Step 3: Inspecting table format and styles** 


Let's **format** and **style** the table widget. You are free to explore various options available for your purpose. Kindly copy the following settings and paste them into your app.

a)  **Properties**: This helps you display the collection you created on Appwrite. Later in the tutorial, we will learn about creating queries. You have to copy this **`{{queries.ListDocument.data.documents}}`** in the input field.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ka5puupfo1e98q3vjtzp.png)

b) **Columns**: We have defined these columns in our Appwrite attributes. We have to update and add the following columns, i.e., **title, description, priority, project_assigned, and message**. Note: Define attributes in a small case. Under each column setting, assign the same value to the key as the column name. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5hajr7u690i071rkd4fz.png)

c) **Action Buttons**: Once you add two action buttons,  **Edit** and **View details**, you can explore its settings to style the button. You must add an event handler with "Show Modal" as action and select the view_details **modal**. Do the same in the Edit action button's settings for the **Edit modal**. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulmhorvl3qc4b4c5ifxs.png)

d) **Styles**: Under the table's styles tab, set **Action Button Radius** with 8, **Table Type** as bordered, **Cell Size** as spacious, **Border Radius** as 8.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fb7xmroyolmid5ol837o.png)


**Step 4: Connect modals in the UI**

Let’s add our modals with the **onClick** events to our respective buttons. Inspect each button and navigate to the “**Add event handler**” property to perform this step. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ybelg4sni8oslcp1jgo.png)

Now Click on “**Action**” and set it to “**Show Modal**”. We get to select the action **options** where we put them to our respective modals.

Great !! 👍  We have completed the first part of our application. Now let's move on to the next step. 


## Integrating data sources and creating queries

We have to add 2 data sources, i.e., [Aws](https://docs.tooljet.com/docs/data-sources/s3/) and [Appwrite](https://docs.tooljet.com/docs/data-sources/appwrite/). You can visit these links to read about the steps involved in the integration.

**Step 1: Add Data sources**


**a) Set up AWS:**

1. Create your **account** on AWS
2. Once done, you have to give **access permissions**
3. Create a bucket with your **name** preference
4. You need to collect the access and secret **key** and go to the **ToolJet** tab where you have built the UI
5. On the left-hand side, select **sources** > click on “+” to add data source > Search and select **AWS s3**
6. Now fill in the inputs fields **Access key**,  **Secret key**, and in the **region** select “**Asia Pacific (Mumbai)**”
7. Once you test the **connection**, then save


**b) Set up Appwrite:**

We'll be deploying Appwrite on **DigitalOcean**. To do the this, follow the steps:

1. Sign up for a free account on DigitalOcean, and it may ask for card details for verification purposes while signing up for the first time.

2. Once signed up, you'll receive free $100 credits valid for 60 days from the date of registration. You can use these credits for deploying apps.

3. Now create an Appwrite droplet in your DigitalOcean account from the following link: [https://marketplace.digitalocean.com/apps/appwrite](https://marketplace.digitalocean.com/apps/appwrite).

4. Next, select the capabilities that you want for your Droplet. We will go with the “Basic” option of a shared CPU and at least 1 GB of RAM. Select the cheapest option with Intel CPU with SSD for $5 per month.

5. In the next step, create the login credentials for your virtual machine. You can either add SSH keys or create a root password. Adding SSH keys is the recommended way, but you can go with the root password if you're new.

6. Click on finalize and create. After some time, DigitalOcean will have your virtual machine running.

7. Finally, you can go to the IP address or URL for our new server and log in to the Appwrite console.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awte5z96paaddv384qgf.png)


**Creating collections and documents**

Now let's look into creating collections and attributes in Appwrite.

1. Once you have signed in to the Appwrite console, create a project. Let's call this project: `**bug_tracker**`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c86t62o3bnjf6azss143.png)

2. Go to the Database from the sidebar in the console, and click on the **Add Collection** button. In the modal, enter the collection name as **bug_tracker** and click **Create** button. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vm3izft2r6jh5phoo8i.png)

3. In Appwrite, **Collections** hold **Documents**. We will add a few sample **Documents** to the Collection that we created. You can think of Collections as tables and Documents as rows. But before adding documents, we will need to add **Attributes**. 

4. We will need the following **attributes** for the documents in our collection:

- Attribute ID(key): **title**, Type: **String** (Title of the bug Ex: **Button-alignment**)

- Attribute ID(key): **description**, Type: String (Describe the bug. Ex: **On /user/profile align the "Save details" button to the right**)

- Attribute ID(key): **priority**, Type: **String** (Set it to **low, medium, high**)

- Attribute ID(key): **message**, Type: **String** ( Select a message from the dropdown: Ex: **Resolve Now**)

- Attribute ID(key): **project_assigned**, Type: **string** (Project where the bug is found. Ex: **Website**)

- Attribute ID(key): **preview_url**, Type: **string(URL)** (URL of the picture of the bug's screenshot)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zi8hzo495gxybss3bzoj.png)

5. Finally, you can start adding documents to the collection.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28n0f5vsx8b8t7fjsj0i.png)


Let's look at the steps for adding the Appwrite data source:

1. Go to the left sidebar, and click on the **Datasource**.
2. In the modal that pops up, select the Appwrite data source.
3. You'll be asked to enter the - **Host, Project ID, and Secret Key**. You'll find these three in your Appwrite console.
4. Now click on the **Test Connection** button to verify that the Appwrite server is connected successfully.  
5. Click on **Save** to add the data source.

Cheers!! 😍 We have added our data sources. Now, let's create different **query operations** required to integrate into our application.

**Step 2:  Creating queries**

These are the following queries we are going to create. I will describe each step in detail. Click on the '+' icon on the left and select **AWS S3** or **Appwrite** as dataSource for respective queries.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0p4cdx7h4rasoilhhr48.png)

Let's create our first Query to connect the AWS bucket we made in our previous step.


1. **UploadImage**: Name of the query. We upload the file picked by our file picker widget to our AWS bucket. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrkmgjfqbrz6z09l67gv.png)

Please select the following details and fill them in, respectively. These components are from our **create_new_bug **modal, so you set them accordingly.  

a) **Operation**: Upload Object
b) **Bucket**: The bucket you created in your AWS dashboard. I have named mine 'tooljet-bucket.'
c) **Key**: `{{components.filepicker2.file[0].name}}`
d) **Content-Type**: `{{components.filepicker2.file[0].type}}`
e) **Upload Data**: `{{components.filepicker2.file[0].base64Data}}`
f) **Encoding**: base64

Once done, `SAVE` this query. 
 

2. **Download**: Name of the query. We are downloading the signed URL to preview in our app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnjbzn7o1pff73klv0zc.png)

We need to add the following:

a) **Operation**: Signed URL for download
b) **Bucket**: Name of the bucket where we are downloading the preview URL
c) **Key**: It should be the name of the file. `{{components.filepicker2.file[0].name}}`
d) **Expires** **in**: Set it to 36,0000

Congratulations!! We have successfully set up our first queries. Now let's create Queries with the following names to connect the **Appwrite** to perform the basic **CRUD** operations. 


3. **ListDocument**: To list all the documents we created in our collections on Appwrite. Copy and paste the following values. 

a) **Operation**: List Document
b) **Collection ID**: Under settings, you will get this in your **Appwrite** dashboard.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odmuy5pkv3nh5c7z2jd5.png)
 
Under the "Advanced tab," toggle on "Run this query on page load." Once done, save the query.


4. **createNewDoc**: To **add** new entries to our collection. Fill in the following fields.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl8dip4tjsn8c6gquqhg.png)

a) **Operation**: Add Document to Collection
b) **Collection ID**: You will get this in your **Appwrite** dashboard under **settings**.
c) **Body**: Add the following key-value pairs. This is the data format in which our Appwrite collection will **receive** data. 

`{"title": "{{components.textinput4.value}}","description":"{{components.textarea3.value}}","project_assigned": "{{components.dropdown7.value}}","priority": "{{components.dropdown8.value}}","message": "{{components.dropdown9.value}}","preview_url":"{{queries.Download.data.url}}"}`

You can save the query once you confirm all the components.



5. **DeleteDocument**- To delete a document in the collection

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjbydihjknu1f8f9lf6j.png)

Add the following:

a) **Operation**: Delete Document
b) **Collection ID**: You will get this in your **Appwrite** dashboard under **settings**.
c) **Document ID**: It is nothing but the selected row id. `{{queries.ListDocument.data.documents[components.table1.selectedRowId].$id}}`

Once done, save this query. Now let's take a look at our last query. 



6. **UpdateDocument**: To update a particular document in the **collection**.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2fqgz20n3mknhxklry2.png)

a) **Operation**: Update Document
b) **Collection ID**: You will get this in your Appwrite dashboard under settings.
c) **Document ID**: It is nothing but the selected row id. `{{queries.ListDocument.data.documents[components.table1.selectedRowId].$id}}`
d) **Body**: Add the following key-value pairs. This is the data format in which our **Appwrite** will **receive** data and update the collection. 

`{"title": "{{components.textinput3.value}}","description":"{{components.textarea2.value}}","project_assigned": "{{components.dropdown4.value}}",    "Priority":"{{components.dropdown5.value}}","message": "{{components.dropdown6.value}}",    "preview_url":"{{queries.ListDocument.data.documents[components.table1.selectedRowId].preview_url}}"}`

Save the query once the details are filled up correctly. 

Amazing!! 🤩  We have created all our queries. We need to connect these queries in our app on button clicks as a next step now.


## Connecting event handlers

Now that we have built the user interface and created all the queries, all we need to do is connect the UI with queries. Let's get started:

- Go to the **Create_New_Bug modal**, inspect the "**Create**" button widget and add the following **six-event** handlers in the same **sequence**:
  
a) **Set Variable**: Select the following action and add key as "**new_bug_status**" and set the value `{{true}}`. Go to the Advanced tab under the **ListDocument** query setting and click on "**add a handler**". In **action**, select "**set Variable**", **key** as **new_bug_status**, and value as `{{false}}`. In creating a button, also update the loading state programmatically with the following value: `{{variables?.new_bug_status ?? false}}`. This will allow a loading stating while queries are being processed.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82qoc4zqjwu1s5f4vxna.png)

b) **Run Query**: Select the following action and add query as "**uploadImage**."
c) **Run Query**: Select the following action and add query as "**Download**."
d) **Run Query**: Select the following action and add query as "**createNewDoc**."
e) **Run Query**: Select the following action and add query as "**ListDocument**."
f) **Close Modal**: Select the following action and add modal as the current modal name, i.e., **Modal3** in this case. 


- Go to the Edit_Bug modal, inspect the "Delete" button  and add the following three event handlers in the same sequence: 

a) **Run Query**: Select the following action and add query as "**DeleteDocument**."
b) **Run Query**: Select the following action and add query as "**ListDocument**."
c) **Close Modal**: Select the following action and add modal as the current modal name, i.e., **Modal2** in this case. 



- Go to the Edit_Bug modal, inspect the "Update" button  and add the following three event handlers in the same sequence: 

a) **Run Query**: Select this action and add query as "**UpdateDocument**."
b) **Run Query**: Select the following action and add query as "**ListDocument**."
c) **Close Modal**: Select the following action and add modal as the current modal name, i.e., **Modal2** in this case. 


We have successfully connected the queries and UI, and our app is fully functional now. You can now understand the reason behind the sequencing queries in such a way. Now, we can perform any **CRUD** operation and check all the flows in our app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhqdyxssi8jx1l94e89z.png)

Congratulations!! 🚀 You have successfully built your bug-tracker application. I hope you had a good time building something new today, and you can start working on this app directly by selecting this template when you create a new application.

We are continuously integrating different data sources with ToolJet. Stay in the loop to read upcoming articles to develop useful internal tools. If you have any trouble building this application, please join our [Slack community](https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg) or email us at **hello@tooljet.com**.