Building a MinIO file explorer app in 30 minutes
Tags: javascript, programming, webdev, beginners
Published: 2022-09-02 08:31:14

> In this tutorial, we will build an internal tool for reading, downloading and uploading objects to the buckets in MinIO.

## What is MinIO?

[Minio](https://www.minio.io/) is an open-source distributed object storage server designed for Private Cloud infrastructure providing S3 storage functionality. Minio is can be used for storing unstructured data such as photos, videos, log files, backups, and containers.

## What you'll need to build the GCS file explorer?
- **ToolJet** ([https://github.com/ToolJet/ToolJet](https://github.com/ToolJet/ToolJet)): A free and open-source low-code platform that allows you to quickly build applications. You can create a free account on [ToolJet Cloud](https://www.tooljet.com/) or run it on your [local machine](https://docs.tooljet.com/docs/setup/).
- **MinIO**: Check out the various editions and their [Pricing](https://min.io/pricing) here. I have used the community edition using docker for this tutorial.

**Bonus**: [Download the exported application](https://blog.tooljet.com/content/files/2022/08/file_explorer_minio-export-1661898635143.json) and import it to your ToolJet account to use it right away. 

Here's a glimpse of the application:

![gir](https://blog.tooljet.com/content/images/2022/08/miniodemo.gif)

Without further ado, let's start building the application.

---

## Building the UI of the explorer

Let's start with building the UI for Explorer. Login to ToolJet and then on the **Dashboard**, click on the **Create new application** button to create a new app. Once the app is created, you will be redirected to the visual app editor. You can change the name of the app by editing the default name i.e **Untitled app** from the top left of the app builder.

![gif](https://blog.tooljet.com/content/images/2021/12/login-1.gif)

### The visual app editor has 4 sections:

- **Canvas** is at the center, where you'll drag and drop widgets to build UI.
- **[Query editor](https://docs.tooljet.com/docs/tutorial/building-queries)** at the bottom, where you can create queries.
- On the right sidebar, you'll find **[Widget Manager](https://docs.tooljet.com/docs/tutorial/adding-widget/)** which has a list of built-in widgets and components. You can drag and drop to start building out the user interface.
- On the left sidebar, you'll see the Inspector, debugger, comments, settings, and **[Datasource manager](https://docs.tooljet.com/docs/tutorial/adding-a-datasource)**. The datasource manager is used to add a new datasource or manage the connected datasource.

### Let's build the UI

For building the user interface, you’ll need to drag and drop the following components from the Widget Manager(right sidebar) and place them accordingly.

Here is the configuration of widgets that I used for building the UI:

- A **Container** as header and **Text widget** inside the container to give a title to the app i.e **MinIO File Explorer**

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--1-.png)

- Another **container** below the header will contain all the sections of the application. Give this container a background color of your choice from the Styles.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--2-.png)

- Let's add a **text** widget in the center and set the text to `Please select a bucket` - we will display this text by conditionally disabling the visibility of the container that we will add on top of this text widget

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--3-.png)

- Let's drag a **container** on top of the text widget, and put list view widget inside the container. You can also use **text** widgets to set columns names- Name, Last updated, Size, and Actions.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--4-.png)

- In the **List view** widget, use text widget for name, updated on, and size. Use Image widget for the Action. User will click on the **download** image to download the object from the MinIO.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--5-.png)

- Set the following field value for the three text widgets Name, Updated on, and Size as `{{listItem.name}}`, `{{moment(listItem.lastModified).format("DD/MM/YYYY h:mm:ss a")}}`, and `{{(listItem.size/1024).toFixed(2)}}` kb respectively. In the image widget set the loading state value to `{{listItem.id === variables.currentlyLoadingId}}` , and add the event handler to open the webpage `{{queries.urlfordownload.data.url}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--6-.png)

- Drag a **button** on the right side of the container that will be used to trigger the dialog for **choosing the bucket**.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--7-.png)

- Drag a **modal** somewhere below the container, go to the button properties and set the **event handler** to **show the modal** that you have added.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--8-.png)

- Click on the button to show the modal, and then you can drag and drop **dropdown** and **button** widget inside the modal to build the modal UI. The dropdown will include the list of buckets that we will retrieve from the query, and the button will have an event handler to fire the query for listing the files from the selected bucket.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--9-.png)

- Let's add text widget next to button for showing up the currently selected bucket. Set the **text** value as `{{components.dropdown1.value}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--10-.png)

- Now, the last section of the UI - the **upload** section. We will build this section inside a container. We will be using **text, divider, text input, file picker and button** widget to build the section. The button widget will include an event handler for firing up the **upload** query that we will create later.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--11-.png)

> 💡 Check the documentation to learn more about customizing the widgets and beautifying the UI. ✨

Now, we are done building the UI - let's move forward with connecting the MinIO and build the queries.

---

## Connecting the MinIO datasource and creating queries

Before creating the queries let's connect the MinIO datasource first:

- Go to the datasource manager on the left sidebar and click on + button to **add a new datasource**.
- Search and click on **MinIO**.
- Enter the **Host, Port, Username and Password**.
- You can click on `Test connection` button to check the connection and then click on **Save** button to save the datasource.
- Now, we are good to go for creating queries.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--12-.png)

**For this application, we will need to build the queries for:
**

- JavaScript code for triggering show modal action
- Listing the buckets from MinIO
- Listing the object/files from the selected bucket
- Uploading the file to the selected bucket
- Creating signed URL for downloading the object from the bucket

### JavaScript code for triggering show modal action

- Go to the Query Panel, and click on the `+` button
- Create a new `JavaScript code query` and enter the following code for triggering the show modal action:
```javascript
actions.showModal('modal1')
```

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--13-.png)

- Go to the **Advanced** tab, toggle on the **Run query on page load?** option, and save the query as **showModalOnPageLoad**. Enabling the Run query on page load option will display the modal every time the app is loaded - giving users the flexibility to choose the bucket before moving to other app functions.

### Listing the buckets from MinIO

- Go to the Query Panel, and click on the **+** button to create a new query
- Select **MinIO** as the datasource
- In the **operations** dropdown, select the **List buckets** option

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--14-.png)

- Go to the **Advanced** tab, toggle on the **Run query on page load?** option, and click **Save and Run** button.
- Let's open up the modal by clicking on the **change** button, and then edit the properties of the dropdown inside the modal. Set the **Option Values** and **Option Label** as `{{queries.listBuckets.data.map(row => row.name)}}` , the Default value to `{{queries.listBuckets.data.map(row => row.name)[0]}}`, and **Options loading state** to `{{queries.listBuckets.isLoading}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--15-.png)

### Listing the object/files from the selected bucket

- Go to the **Query Panel**, and click on the **+** button to create a new query
- Select **MinIO** as the **datasource**
- In the **operations** dropdown, select the **List objects in a bucket** option
- In the **Bucket** field, use JS to dynamically get the value from the selected option in the dropdown widget - `{{components.dropdown1.value}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--16-.png)

- Now, go to the **Advanced** tab and add an **event handler** to **close the modal** once the **query is successful**.
- **Save and run** the query as **listFiles**.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--17-.png)

- Let's open up the **modal** by clicking on the **change** button, and then edit the properties of the button that is inside the modal. Add an **event handler** for running the **listFiles** query for **On Click** event.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--18-.png)

- Go to the **list view** widget and connect the data returned by the query. Set list data field value to `{{queries.listFiles.data.files}}`

### Uploading the file to the selected bucket

- Go to the Query Panel, and click on the **+** button to create a new query
- Select **MinIO** as the **datasource**
- In the **operations** dropdown, select the **Put object** option
- In the **Bucket** field enter `{{components.dropdown1.value}}` , **File name** field enter `{{components.textinput1.value}}` , **Content type** field enter `{{components.filepicker1.file[0].type}}` , and **Upload data** field enter `{{components.filepicker1.file[0].content}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--19-.png)

- Go to the **Advanced** tab and add the two event handlers, one to run the **listFiles** query for the On Success event. This will reload the list of files in the listview widget.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--20-.png)

- And the other event handler to set **component specific action** for file picker that will clear the file from the widget once the query is successful.

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--21-.png)

- **Save and run** the query as upload.

### Creating signed URL for downloading the file from the bucket

- Go to the Query Panel, and click on the **+** button to create a new query
- Select **MinIO** as the **datasource**
- In the **operations** dropdown, select the **Presigned URL for download** option
- In the **Bucket** field enter `{{components.dropdown1.value}}`, and in **File name** field enter `{{queries.listFiles.data.Body[components.listview2.selectedRowId].name}}`

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--22-.png)

- Go to the **Advanced** tab and set an **event handler** to `unset a variable` - **currentlyLoadingId**

![cont](https://blog.tooljet.com/content/images/size/w1600/2022/09/output-onlinepngtools--23-.png)

- Save the query as **urlfordownload**
- Go to the **list view** widget and click on its handle to **edit its properties**.
- Add the **two event handlers**- one to **set a variable** `currentlyLoadingId` for **On row click** event and set its value to `{{queries.listFiles.data.Body[components.listview2.selectedRowId].name}}`
- And the other **handler** to run the **urlfordownload** query.
- Now you can click on one of the row on the list view widget and it will fire up the urlfordownload query.

**Awesome! We have successfully built all the queries and connected with the UI.**

---

And now FINALLY just **Release** your application from the top right corner of the app editor.

You have successfully created a **File explorer app for your MinIO object storage** 🎉

---

If you have any queries related to building applications with ToolJet or just want to hang out in the community of low-code application developers just drop us a Hi in our [Slack Community](https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg). 🚀