KQL Search

Introduction

This is the final website: KQLSearch.com

You can find the full code here on GitHub: KQL-Search

Overall Architecture of the Web Application:

Deployment
Web App

Motivation for this project

I started this project because I wanted to further learn JavaScript and React. The best part was to connect two of my interests Coding and Microsoft Intune (Endpoint Management).

I have long thought about how I could combine these two interests and develop myself. It had to be a project which should also be fun so that I don’t lose any motivation to keep pushing. Then I had the idea to create this website.

This web page searches in real time for KQL queries in three given GitHub repositories.

What have I learned

  • Using JavaScript and the GitHub API to query data in GitHub.
  • Using React to display this data in a UI.
  • Using Postman to test API queries and authorization with GitHub.
  • Using Vercel to Deploy the Application and assign the domain.

What was my approach?

I am by nature not one to learn with videos or from blogs alone. I learn best with my own projects and the troubleshooting that will come with it. But be careful: It can also become demotivating very quickly if too many things don’t work and you have to search the internet for every error message.

I started working on this web application without any great planning. This had a big disadvantage: The features of the website became more and more during the implementation. Instead of reaching a status quo in time X the project got bigger and bigger until I decided to postpone new features into the future.

So that I don’t forget any ideas, I always had a notepad open in which I also wrote my to-dos. This helped me a lot in organizing my thoughts. I can only recommend such an approach.

The beginning was much easier for me because of the create-react-app function. With that, I already had a working foundation for my project. Now I had to venture to the GitHub API, with which I can display the data from the repositories. For this I used axios. The first time I tried it, the authentication failed. However, I was able to solve this quickly with an .env file. I also used variables in the link to the GitHub API for the extensibility of the web application so that I can use it for other repositories in the future:

It was also important that I could filter the data in the response, because I didn’t need all the files in the GitHub repositories. I was only interested in files with the extensions .kql and .txt. For this I created a filter in a separate file (Filelist.js):

In addition to displaying the file names on the web page, the content of the files should also be displayed. In the first attempt, I had only referred to the GitHub link of the individual files, which I did not find intuitive. To be able to display the content I wrote the following:

To round out the features, I added a search box and a way to filter different categories:

The appearance of the buttons I have adjusted in CSS and added a small animation. In addition, I have adapted the content of the site so that parts such as the footer, the flex box wide to the display size of the user is adapted. Some things I had to hide for clarity if the display was too small. Example:

After I was happy with the web app, it was time to clean up the code. For this I used Prettier. It’s very easy to install as an add-on in VS Code and apply Shift+Alt+F. This helped extremely because the code suddenly became more readable. I now learned to write readable code in the first place, because I didn’t know where anything was anymore and lost a lot of time searching. I didn’t have any time pressure in general, but it annoyed me to waste time on such trifles, which I could have used just as well for a new project.

Detailed explanation

app.js

This code defines a React functional component called App that fetches a list of files from three different repositories on GitHub and displays them in a list. The component has several state variables:

  • intuneFiles: an array of files from the “ugurkocde/KQL_Intune” repository.
  • sentinelFiles: an array of files from the “reprise99/Sentinel-Queries” repository.
  • otherFiles: an array of files from the “rod-trent/SentinelKQL” repository.
  • query: a string representing the current search query.
  • filter: a string representing the current prefix filter applied to the list of files.

The component also has several functions:

  • handleSearch: a function that updates the query state variable with a new search query.
  • handleFilter: a function that updates the filter state variable with a new prefix filter.

The component makes use of the useEffect hook to perform an initial fetch of the files from the three repositories when the component mounts. The fetched files are stored in the appropriate state variables depending on the repository they come from. The useEffect hook is passed an empty array as its second argument to ensure that the fetch is only performed once when the component mounts.

The component also makes use of several child components: FileList, SearchBar, Statistics, NavigationButton, Socials, and Footer. These child components are responsible for rendering different parts of the UI.

The App component renders a search bar and a list of files, and it allows the user to filter the list of files by prefix and to search for a specific file by name. When the user submits a search query or selects a prefix filter, the relevant state variables are updated, which triggers a re-render of the component and updates the list of displayed files accordingly.

filelist.js

This code is a functional component in a React application. The component accepts several props:

  • files: an array of file objects
  • query: a string representing the current search query
  • prefix: a string representing the prefix of the file name
  • filter: a string representing the current filter applied to the files

The component initializes several state variables using the useState hook:

  • selectedFile: a file object representing the currently selected file
  • fileContents: a string containing the contents of the currently selected file

The component defines a handleFileClick function that is called when a file is clicked. If the clicked file is already the selected file, the function sets selectedFile and fileContents to null to close the file. Otherwise, the function makes an API call to retrieve the contents of the file and sets selectedFile and fileContents to the file and its contents, respectively.

The component then filters the files array based on the query and filter props. If the filter prop is not equal to “All”, the resulting filtered array will contain only those files with names that include the query string and end with either the “.kql” or “.txt” extension. If the filter prop is equal to “All”, the resulting filtered array will contain all files with names that include the query string. If the prefix prop is equal to “Other”, the resulting filtered array will contain only those files with names that include the query string and end with the “.txt” extension.

The component then displays the filtered list of files as a list of list items. Each list item contains the file name and a button that allows the user to copy the file path to the clipboard. When a file is clicked, the handleFileClick function is called and the file contents are displayed below the list of files.

SearchBar.js

This code defines a SearchBar component in a React functional component. The component has two state variables, query and filter, which are initialized using the useState hook.

The component renders a search input field and a dropdown menu for selecting a filter value. The component also defines two event handlers, handleChange and handleFilter, which are passed as props to the input field and dropdown menu respectively. These event handlers update the component’s state variables when the input field or dropdown menu are changed by the user.

The component also receives two props, onSearch and onFilter, which are functions passed down from the parent component. These functions are called with the updated query and filter values as arguments whenever the input field or dropdown menu are changed by the user. This allows the parent component to react to these changes and perform some action, such as updating a list of files being displayed based on the search query or filter value.

Finally, the component returns JSX that renders the search input field and dropdown menu, along with some styling applied to the elements.

What I would like to add in the future

Caching Server / Database:

A possible improvement would be to introduce a database that is filled once a day with the answers from GitHub. Currently, every visit to the website means a new query with the GitHub API. I could avoid that with a database. The frontend would then fetch the data from the database. The use of MongoDB would possibly make sense here.

Conclusion

The project was extremely valuable for me to work more with Javascript and React. I also worked with the GitHub API for the first time and hosted the code on Vercel. All around very successful even though there is certainly room for improvement. I will continue to maintain the website and work up feedback, but at the same time start a next project and take the momentum with me.

Thank you for reading and until next time.

Ugur Koc