Building Recruitment Management App using Appwrite and ToolJet

Building Recruitment Management App using Appwrite and ToolJet
This tutorial will guide you to easily build a recruitment management application in less than 30 minutes using ToolJet's low-code application builder.

The recruitment management app will allow you to manage your organization's recruiting and staffing operations. Use this application for keeping your applicants connected and engaged throughout your entire recruiting process.

Here are some of the main features of this application:

  • Applicants tracking options like approving or rejecting applicants.
  • Engage with applicants or schedule interviews using email.
  • Limit features like adding applicants depending on the current user or user group type.

To build this application we will use:

  • ToolJet (https://github.com/ToolJet/ToolJet): A free and open-source low-code platform that allows you to quickly build applications. Sign up here.
  • Appwrite: Open-Source backend server for Web, Mobile & Flutter developers. For this application, I have deployed Appwrite on DigitalOcean using the Appwrite droplet.
  • SMTP: SMTP server for sending emails to applicants. Read the docs for the SMTP data source here.
đź’ˇ
Need help with building your own application or just want to hang out in the community or low-code application builders? Feel free to join our Slack community 🚀

The tutorial is broken down into the following sections:

  1. Setting up Appwrite
  2. Creating collection and documents in Appwrite
  3. Adding Appwrite data source on ToolJet
  4. Building the app UI
  5. Creating queries
  6. Editing widget properties and connecting queries
  7. Enabling app features for particular User Group

Setting 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, 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
đź’ˇ
The Droplet is a virtual machine in the cloud and can be as simple as a single shared CPU with 1 GB RAM and 25 GB storage for $5 a month. One of the main selling points of Appwrite is its ability to thrive on this size of infrastructure for small projects.

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 which is 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 if you're new you can go with the root password.

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.


Creating collections and documents in Appwrite

  1. Once you have signed in to the Appwrite console, create a project. Let's call this project: recruitment-management

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 Applicants and click Add button.

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.

đź’ˇ
Each attribute has a key, attribute type, default, required, and array properties, which define the type and structure of expected data. Think of them as columns in a traditional relational database.

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

  • Attribute ID(key): name, Type: String (Name of the applicant)
  • Attribute ID(key): birthdate, Type: String (Birthdate of the applicant. Ex: DD-MM-YYYY)
  • Attribute ID(key): city, Type: String (For the  city of the applicant)
  • Attribute ID(key): phone, Type: integer (Phone number of the applicant. Ex: 1234567890)
  • Attribute ID(key): email, Type: string(email) (Email of the applicant. Ex: abc@xyz.com)
  • Attribute ID(key): resume, Type: string(URL) (URL of the resume of the applicant. Ex: https://drive.google.com/xxxxx)
  • Attribute ID(key): position, Type: String (Position for which the applicant applied. Ex: Frontend Developer)
  • Attribute ID(key): picture, Type: string(URL) (URL of the picture of the applicant. Ex: https://www.imgr.com/xxxx)
  • Attribute ID(key): approved, Type: String (Status of the Applicant. This will include any one of these values - new, yes, or no)

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

đź’ˇ
While adding documents, make sure to enter new as the value for the approved key. We will use new for new applicants and later update the value for approved as yes or no.

Adding Appwrite data source on ToolJet

I am assuming that you have already created an account on ToolJet and logged in to the dashboard. Now click on Create new application button and then give your first version app a name then click Create.

Before we start with setting up the Appwrite data source, let me give you a quick walkthrough of the ToolJet App Editor:

Now 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. Now 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.
đź’ˇ
Check out the ToolJet's documentation for Appwrite data source to know about all the available operations.

5. Click on Save to add the data source.


Building the application UI

Now that we have connected the data source, the next steps are to build the user interface, create the queries for performing several operations, and then connect the UI and queries to make our app functional.

For building the application UI, we will use the following widgets:

  • Containers
  • Circular progress bars
  • Modals
  • List view
  • Buttons

Here's how your application will look in the end:

Let's start building the UI:

  • Drag and drop a Text widget to canvas and click on it to open the widget properties inspector panel on the right sidebar. We will use the HTML heading tags <h1> to style our text. Enter <h1>Recruitment Management Dashboard</h1> in the Text field.
  • Now drag a container, and place it below the Title of the app. We will use this container to display approved applicants' stats using a circular progress bar and text. Follow the steps to build the UI:
    • Click on the container's widget handle to open the properties. In the Styles tab, Add #667ACD as the hex color code for the background and set the Border radius to 10.
    • Drag a text widget inside the container, add the text as Summary of approved and set the text color to #FFFFFF
    • Drag two more text widgets that will be used to display the approved number of applicants from the query and the total applicants. We haven't yet created the queries so for now let's add dummy text to these two widgets and place them. For the first text widget add 1/ and second text widget 2.
    • Now drag the circular progress bar inside the container and click on the widget handle to edit its properties. Go to Styles and change the color to #F39200, we'll edit the remaining properties later once we have created the queries.
  • Now we will duplicate the component that we created in the previous step. This will be used to display the number of rejected applications. To duplicate, click on the handle of the container and press cmnd/ctrl+d. You'll see a duplicate component overlapping the first one. Drag the duplicate container and place it next to the first one.
  • Now, make changes in the text and color of the duplicate container. It will include duplicate widgets of all the widgets that are there in the first container.
  • Now drag a button next to the container of Summary of rejected applicants. We will use this button to trigger a modal - that will have a form for adding new applicants. So, we will add the text Add applicant on this button. For Styling, set the Border radius 10 and color to #F39200.
  • Let's duplicate the button and rename its text to Refresh. This button will be used to refresh the list of applicants.
  • Now we will need to build a sidebar on the right to show the selected applicant basic details that will include some buttons for performing actions like checking resume, sending email, and approving or rejecting the selected applicant. To build the left sidebar, follow the steps:
    • Drag a container on the right of the buttons and adjust its height to reach the bottom of the canvas.
    • Let's start putting the widgets inside the container. We'll start by putting the image widget on the top of the container. It will be used for displaying the selected applicants' pictures. Go to the Style of image widget and choose border type as the circle.
    • Now drag a text widget below the image widget, edit its properties and enter the dummy text for now. We'll get the value from the selected applicant once we are done creating queries.
    • Now we'll need to drag a few more text widgets and fill the dummy text values for displaying the Basic Information such as Birthdate, City, Phone Number, and Email. (Check the next screenshot)
    • Now add a button below the basic information that will be used to open the resume. Edit the properties of the button - Fill the text value as Resume. Go to the Style, set the background color to #D4DAF1, text color to #000000, and border radius to 20.
    • We'll duplicate the button created in the previous step using cmnd/ctrl+d. Edit the text on the button to Send Email. This button will be used to show the modal that will include the fields for sending emails to the selected applicants.
    • Now add a new button at the bottom-left for Accepting the selected applicant. Let's resize the button to make it a square button. Set the button text to Approve. Go to the Style, set the background color to #909EDB and border radius to 20.
    • Duplicate the button for accepting the applicants, change the text to Reject. Go to Style, update the color to #DD7179.

We are almost done with 50% of the user interface. All we need to do now is to build the UI for displaying the New Applicants list, Accepted Applicants list, Rejected Applicants list, Add Applicants modal, and Send Email modal.

Let's build the UI for the New Applicants list:

  • Drag a Container in the center and scale it to occupy the remaining blank space. Set the border radius of the container to 10.
  • Drag a Text to top-left of the container and set the Text field value to <h2> New Applicants </h2 >
  • Drag a new container within this container and scale it horizontally from the left to right of the parent container. Use three text widgets within this container and change the text to Name, Email, Resume, and Position respectively. Check the screenshot below.
    Screenshot-2022-04-25-at-1.54.25-AM-1
  • Now, drag a List view widget below the child container that we added above. We'll add a few widgets inside the first row of the List view widget. Set the Row height of the List view to 80.
  • Add the Image widget below the Name, set the URL of the Image widget to {{listItem.picture}} and border type to circle. Read List view docs to learn more about showing data.
  • Add a Text widget next to the image and set the text field to {{listItem.name}}
  • Similarly a text widget under Email and Position and set the value to {{listItem.email}} and {{listItem.position}} respectively.
  • For the Resume, we will add a Button and add an Event handler to the button. Set Event to On click and choose action Open webpage. Set the webpage URL to {{listItem.resume}}.
    The New applicant section should look similar to the screenshot but with just one row in the list because we haven't yet added the data to the list. We'll add the data to the List view after we are done creating the queries.
    Screenshot-2022-04-25-at-2.16.04-AM-1

Now let's duplicate the container for the New Applicants twice to create two new lists for Accepted and Rejected. See the screenshot below:

Finally, let's add a Modal for Add Applicants button. Drag a modal at the blank space below the lists. Now, go to the Add Applicants button and add a handler for the On Click event and Show Modal action, and select the modal1 in the dropdown.

Now when you'll click on the Add Applicant button the modal will show up. You can drag and drop widgets from the widgets manager in the left sidebar and create a form like this:

Let's add another Modal for Send Email button, add an event handler in the Send Email button the same way we did for Add Applicant button but choose Modal2 in the dropdown.

Click on the Send Email button to show up the modal and then add the widgets to build the form for sending email as shown in the screenshot. Use Text, Text Input, Text Area, and Button widgets to create this form:

Finally, we are done with building the User Interface of the application. Now the next step is to create queries to perform operations on the Appwrite database and then connect the queries and user interface.


Create the queries

To make our application fully functional we'll be creating these queries:

  1. listApplicants (Appwrite)
  2. approvedApplicants (Appwrite)
  3. rejectedApplicants (Appwrite)
  4. addApplicant (Appwrite)
  5. moveToApprove (Appwrite)
  6. moveToReject (Appwrite)
  7. sendEmail (SMTP)
  8. totalApplicants (Custom JavaScript)

1.  listApplicants

This query will be used for listing the new applicants. Let's create a new query by clicking on the + in the query panel.

  • Select the Appwrite data source and choose the operation List Documents.
  • Enter the Collection ID, you can get it from the Appwrite console.
  • We will filter the query results using Field, Operator, and Value options. We want the query to list only new applicants so we will enter approved in Field, == in Operator, and new in Value. You'll need to create an index in the Appwrite console for approved key.
  • Go to the Advanced tab and enable the toggle for Run this query on page load? This will fire the query every time the app is loaded.
  • Rename this query to listApplicants and click Save.
  • You can also click on the Preview button to check the results without firing up the query.

2. approvedApplicants

This query will result the list of only those applicants that have yes value in approved column/key.

  • Create a new query, select Appwrite data source, and select the List Documents operation from the operations dropdown.
  • Enter the Collection ID
  • In the Field, Operator, and Value fields enter approved, ==, and yes respectively. (make sure you have added an index for the approved key)
  • Rename this query to approvedApplicants and click Save to create the query.
  • Now go to the Advanced tab of listApplicants query, add an event handler to run the query approvedApplicants on Query Success event.

3. rejectedApplicants

This query will result the list of only those applicants that have no value in approved column/key.

  • Create a new query, select Appwrite data source, and select the List Documents operation from the operations dropdown.
  • Enter the Collection ID
  • In the Field, Operator, and Value fields enter approved, ==, and no respectively. (make sure you have added an index for the approved key)
  • Rename this query to rejectedApplicants and click Save to create the query.
  • Now go to the Advanced tab of approvedApplicants query, add an event handler to run the query rejecteedApplicants on Query Success event.

4. addApplicant

This query will be used for adding a new applicant.

  • Create a new query, select Appwrite data source, and select the add a document to the collection operation from the operations dropdown.
  • Enter the Collection ID, you can get it from the Appwrite console.
  • In the Body field, we'll get the values for the new document in JSON format:
{
    "name": "{{components.textinput3.value}}",
    "birthdate": "{{components.textinput4.value}}",
    "city": "{{components.textinput5.value}}",
    "phone": {{components.textinput6.value}},
    "email": "{{components.textinput7.value}}",
    "resume": "{{components.textinput2.value}}",
    "position": "{{components.textinput8.value}}",
    "approved": "new",
    "picture": "{{components.textinput9.value}}"
}
đź’ˇ
We are getting values from the components that we added in Modal1. While creating the query you can verify by entering values in the form and then the code hinter will display those values.
  • Go to the Advanced tab, and add three event handlers. 1st one to close the Modal1 on Query Success event, 2nd to show alert Applicant Added with alert type as Success on Query Success event, and last one to run the query listApplicants on Query Success event - this will refresh the list and include the recently added applicant.
  • Rename this query to addApplicant and click Save to create the query.

5. moveToApprove

This query will move the selected applicant from New Applicants list to the Approved Applicants list. This query will be triggered from the Approve button in the sidebar.

  • Create a new query, select Appwrite data source, and select the Update Document operation from the operations dropdown.
  • Enter the Collection ID
  • In the Document ID, we will enter {{queries.listApplicants.data.documents[components.listview1.selectedRowId].$id}}. This is getting the Document ID of the selected applicant from the list.
  • In the body field, we'll enter the updated document as JSON object.
{
    "name": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].name}}",
    "birthdate": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].birthdate}}",
    "city": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].city}}",
    "phone": {{queries.listApplicants.data.documents[components.listview1.selectedRowId].phone}},
    "email": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].email}}",
    "resume": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].resume}}",
    "position": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].position}}",
    "approved": "yes",
    "picture": "{{queries.listApplicants.data.documents[components.listview1.selectedRowId].picture}}"
}

So basically we are updating just one key in the document that is the approved key - updating its value from new to yes.

Now go to the Advanced tab and add two handlers - One to show the alert Applicant Approved on query success and the other to run the query listApplicants on query success.

  • Rename this query to moveToAccept and click Save to create the query.

6. moveToReject

This query will move the selected applicant from New Applicants list to the Rejected Applicants list. This query will be triggered from the Reject button in the sidebar. Under the hood, we will be just updating the value for approve key from new to no.

There is no difference in this query from moveToApprove query - except in that query we were updating the value of approve key from new to yes and in this one will be updating it to no.

  • Go to the Advanced tab, and add two handlers - One to show the alert Applicant Rejected on query success and the other to run the query listApplicants on query success.
  • Rename this query to moveToReject and click Save to create the query.

7. sendEmail

This query gets the values from Modal2 which is shown when Send Email button is clicked. Before creating this query, you'll need to add the SMTP data source. Check the docs for adding SMTP data source.

  • Create a new query, and select SMTP data source.
  • Enter the email in From field, and sender's name in From Name field.
  • In the To field, we'll get the value from the selected applicant in the list. We'll use the exposed variable selectedRow to get the value - {{queries.listApplicants.data.documents[components.listview1.selectedRowId].email}}
  • In the Subject field, we'll get the value from the text input component used inside the modal2 - {{components.textinput1.value}}, similarly in the Body field - {{components.textarea1.value}}
  • Go to the Advanced tab, and create two event handlers - one to close the modal2 and the other to show alert Email sent

8. totalApplicants

This query will result the total number of Applicants i.e. New+ Approved+ Rejected. To do this, we'll create a new Custom JS query and write a simple JavaScript code:

var total = parseInt(queries.listApplicants.data.total + queries.approvedApplicants.data.total + queries.rejectedApplicants.data.total);
return total;

We'll use the result from this query on the Summary of approved and Summary of rejected containers to show the number of total applicants.


Editing widget properties and connecting queries

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 Summary of approved section, select the text widget that has 2/ value, and replace the value with {{queries.approvedApplicants.data.total}}/. In the loading state field, enter {{queries.approvedApplicants.isLoading}}.
  • In the text widget that has a dummy value 9 replace it with {{queries.totalApplicants.data}}. In the loading state field, enter {{queries.totalApplicants.isLoading}}.
  • In the Summary of rejected section, enter {{queries.rejectedApplicants.data.total}} to show rejected applicants in the first text widget, and set its loading state to {{queries.rejectedApplicants.isLoading}}.
  • In the text widget that has total applicants enter {{queries.totalApplicants.data}}. In the loading state field, enter {{queries.totalApplicants.isLoading}}.
  • Click on the widget handle of Add Applicant button to open its properties. Set its loading state to {{queries.addApplicant.isLoading}}, and an event handler to show the modal1 for the On Click event.
  • Click on the widget handle of the Refresh button, set the Loading state to {{queries.listApplicants.isLoading}} and add a handler to run listApplicants query on the On Click event.
  • Now, click on the Image in the right sidebar that is built using the container. Enter the URL for the image {{queries.listApplicants.data.documents[components.listview1.selectedRowId].picture}}
  • We'll do the same for basic details (get the data using the selectedRowID variable), for Birthdate enter text value as {{queries.listApplicants.data.documents[components.listview1.selectedRowId].birthdate}}, for the city enter {{queries.listApplicants.data.documents[components.listview1.selectedRowId].city}} , for Phone number enter {{queries.listApplicants.data.documents[components.listview1.selectedRowId].phone}}, and for email enter {{queries.listApplicants.data.documents[components.listview1.selectedRowId].email}}
  • Open properties of the Resume button and add the handler to Open a webpage on On Click. Set the URL to {{queries.listApplicants.data.documents[components.listview1.selectedRowId].resume}}
  • Click on the handle of Send Email button to edit its properties. Add a handler to show the Modal2.
  • Click on the Approve button handle, set the loading state to {{queries.moveToApprove.isLoading}} , and add a handler to run the moveToApprove query.
  • Click on the Reject button handle, set the loading state to {{queries.moveToReject.isLoading}} , and add a handler to run the moveToReject query.
  • Now select the List view widget inside the container of New Applicants. In the List data field enter {{queries.listApplicants.data.documents}}. After entering this you'll see that the list now has all the applicants.
  • We'll do the same for the other two list view widgets - Approved and Rejected lists. For Approved List data enter {{queries.approvedApplicants.data.documents}}, and for Rejected List data enter {{queries.rejectedApplicants.data.documents}}

We have successfully connected the queries and UI and our app is fully functional now.


Enabling app features for particular User Group

Now that we have successfully built the app, we want some of our features like Adding Applicants only available to a certain group of app users. Let's assume you have two types of users who will use this app:

  1. group1 - users who will be authorized to create applicants
  2. group2 - Users who will not be authorized to create applicants but can use other features of the app

To achieve this functionality you'll need to create two groups in your organization and add those users in respective groups. Check out the docs for managing users and groups here.

Let's disable the Add Applicant button for all the users that are not in the group1:

  • Click on Add Applicant button handle to edit its properties.
  • Go to Style, click on Fx next to Disable, and enter {{globals.currentUser.groups[1] !== "group1" ? true : false}}
  • Now whenever a user who is not in the group1 will use the app the Add Applicant button will be disabled.

Finally, make the application live by clicking on the Release button at the top-right corner of the app editor.

Congratulations! 🥳  You’ve successfully built the Recruitment management app. If you have any questions feel free to join our Slack community or send us an email at hello@tooljet.com.