├── .gitattributes ├── .github └── workflows │ └── pylint.yml ├── Procfile ├── Readme.md ├── __pycache__ ├── app.cpython-311.pyc ├── config.cpython-311.pyc ├── settings.cpython-311.pyc └── token.cpython-311.pyc ├── app.py ├── models ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-311.pyc │ └── filter.cpython-311.pyc └── filter.py ├── requirements.txt ├── routes ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-311.pyc │ └── index.cpython-311.pyc └── index.py ├── settings.py ├── static ├── favicon_io │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── site.webmanifest ├── images │ ├── 1.png │ ├── 2.png │ └── 3.png ├── script.js └── style.css ├── templates ├── base.html ├── index.html └── result.html └── wsgi.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/pylint.yml: -------------------------------------------------------------------------------- 1 | name: Pylint 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | python-version: ["3.8", "3.9", "3.10"] 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Set up Python ${{ matrix.python-version }} 14 | uses: actions/setup-python@v3 15 | with: 16 | python-version: ${{ matrix.python-version }} 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip 20 | pip install pylint 21 | pip install -r requirements.txt 22 | - name: Analysing the code with pylint 23 | run: | 24 | pylint $(git ls-files '*.py') 25 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn wsgi:app 2 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Title: Github Repo Search Tool 2 | 3 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 4 | 5 | ## Description 6 | 7 | The Github Repo Search Tool provides enhanced search functionality, allowing users to find repositories based on topics, ratings, and programming languages. 8 | 9 | ## Features 10 | 11 | 1. Search by Topic: The Github Repo Search Tool allows users to search for repositories based on specific topics. Users can enter a topic of interest, and the tool will retrieve repositories related to that topic. 12 | 13 | 2. Search by Top Rated: Users can search for repositories based on their rating or popularity. By specifying a minimum rating threshold, the tool fetches repositories that meet or exceed the specified rating. 14 | 15 | 3. Search by Language: The tool enables users to search for repositories written in specific programming languages. Users can select a programming language from the available options, and the tool will fetch repositories written in the chosen language. 16 | 17 | 4. Sorting by Top Rated: The search results can be sorted by the rating or popularity of the repositories. This feature allows users to view the repositories in descending order of their ratings, helping them identify the most highly rated repositories. 18 | 19 | ## Installation and Configuration 20 | 21 | To install and use this project, please follow the steps below: 22 | 23 | 1. Install Python 3.x on your computer. 24 | 2. Clone the project by running the following command in your terminal: 25 | `git clone https://github.com/epythonlab/github-search-tool.git` 26 | 27 | 3. Navigate to the project's directory structure by running: 28 | `cd github-search-tool` 29 | 30 | 4. Set up and configure the virtual environment in the project directory: 31 | - Open your terminal and run the command: 32 | `python3 -m venv .venv` 33 | 34 | - Activate the virtual environment by running: 35 | `source .venv/bin/activate` 36 | 37 | 5. Install the required dependencies by running the command: 38 | 39 | `pip install -r requirements.txt` 40 | 41 | 7. Obtain your own token from GitHub and replace it in the `settings.py` file. Look for the line: 42 | `TOKEN = 'your token'` 43 | 44 | Replace 'your token' with your actual token. 45 | 46 | Once you have completed these steps, you should have the project installed and configured on your local machine. You can proceed to run the application and explore its features. 47 | 48 | To run the server, execute the following command in your terminal: 49 | `python3 wsgi.py` 50 | 51 | This will start the server, and you will be able to access the application by visiting the appropriate URL in your web browser. 52 | 53 | ## Usage 54 | 55 | After installing and setting up the project, run the server using the command `python3 wsgi.py`. 56 | 57 | Open your web browser and navigate to the URL where the server is running (usually `http://localhost:5000`). 58 | 59 | On the home page, you will see a search form where you can specify your search criteria. 60 | ![Step 1](static/images/1.png) 61 | 62 | Write a topic on the search bar and choose the programming language and rating from the drop-down menu as shown in the above picture to search for repositories related to that criteria. 63 | 64 | Click on the "Search" button to initiate the search. It will show you the waiting message as shown below: 65 | ![Step 1](static/images/2.png) 66 | 67 | The search results will be displayed on the next page, showing the repositories that match your criteria. 68 | 69 | Each repository will be listed with its name, URL, star rating, fork count, and other relevant information. 70 | ![Step 1](static/images/3.png) 71 | 72 | You can click on a repository to view more details and explore its contents. 73 | 74 | 75 | To perform a new search, simply go back to the home page and enter new search criteria. 76 | 77 | Enjoy exploring and discovering interesting GitHub repositories based on your search preferences! 78 | 79 | 80 | ## Contributing 81 | 82 | If you'd like to contribute to this project, please follow these guidelines: 83 | 84 | - Fork the repository 85 | - Create a new branch 86 | - Make your changes 87 | - Submit a pull request 88 | 89 | ## License 90 | 91 | This project is licensed under the [MIT License](LICENSE). 92 | 93 | ## Contact 94 | You can reach out to us on the following platforms: 95 | - Telegram: https://epythonlab.t.me/ 96 | - Facebook: https://facebook.com/epythonlab1/ 97 | - YouTube: https://youtube.com/@epythonlab/ 98 | - LinkedIn: https://linkedin.com/company/epythonlab/ 99 | -------------------------------------------------------------------------------- /__pycache__/app.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/__pycache__/app.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/config.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/__pycache__/config.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/settings.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/__pycache__/settings.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/token.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/__pycache__/token.cpython-311.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | """ 2 | File name: app.py 3 | In this app.py file, you have to define app 4 | and import the routes and register the blueprint 5 | import Flask module 6 | """ 7 | from flask import Flask 8 | 9 | # construct the code app objects 10 | app = Flask(__name__) 11 | 12 | # configure settings and Initialize plugins 13 | app.config.from_object('settings.Config') 14 | 15 | with app.app_context(): 16 | from routes import index 17 | # register the index route 18 | app.register_blueprint(index.index_bp) 19 | -------------------------------------------------------------------------------- /models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/models/__init__.py -------------------------------------------------------------------------------- /models/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/models/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /models/__pycache__/filter.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/models/__pycache__/filter.cpython-311.pyc -------------------------------------------------------------------------------- /models/filter.py: -------------------------------------------------------------------------------- 1 | """ 2 | Filter Model 3 | 4 | This module provides functionality for searching repositories on GitHub based on various filters. 5 | 6 | Attributes: 7 | None 8 | 9 | Methods: 10 | search_repositories_by_topic(language, topic, min_rating, token): 11 | Searches repositories on GitHub based on the specified filters. 12 | get_next_page_url(headers): Retrieves the URL of the next page in the paginated response. 13 | 14 | """ 15 | import json 16 | import requests 17 | 18 | 19 | class Filter: 20 | """ 21 | Filter Model 22 | 23 | This class provides functionality for searching repositories on GitHub based on various filters. 24 | 25 | Attributes: 26 | None 27 | 28 | Methods: 29 | search_repositories_by_topic(language, topic, min_rating, token): 30 | Searches repositories on GitHub based on the specified filters. 31 | get_next_page_url(headers): Retrieves the URL of the next page in the paginated response. 32 | 33 | """ 34 | 35 | def __init__(self): 36 | pass 37 | 38 | @staticmethod 39 | def search_repositories(language, topic, min_rating, token): 40 | """ 41 | Search repositories on GitHub based on the specified filters. 42 | 43 | Args: 44 | language (str): The programming language to filter by. 45 | topic (str): The topic or tag to filter by. 46 | min_rating (int): The minimum rating (stars) a repository should have. 47 | token (str): The GitHub API token for authentication. 48 | 49 | Returns: 50 | list: A list of repository objects matching the specified filters. 51 | 52 | """ 53 | headers = { 54 | 'Authorization': f'Token {token}', 55 | 'Accept': 'application/vnd.github.v3+json' 56 | } 57 | 58 | # url = f'https://api.github.com/search/repositories?q=topic:{topic}+stars:>{min_rating}' 59 | # search query contains 60 | # lanuague, topic or tag and name contains the selected topic 61 | # rating 62 | query = f'language:{language}+in:topic+{topic}+stars:>{min_rating}+in:name+{topic}' 63 | sort = 'stars' # Sort by stars (rating) 64 | url = f'https://api.github.com/search/repositories?q={query}&sort={sort}' 65 | 66 | # store the results in the list 67 | repositories = [] 68 | 69 | while url: 70 | response = requests.get(url, headers=headers, timeout=10) 71 | response_json = json.loads(response.text) 72 | 73 | if response.status_code == 200: 74 | repositories.extend(response_json['items']) 75 | url = Filter.get_next_page_url(response.headers) 76 | else: 77 | print( 78 | f"Request failed with status code {response.status_code}") 79 | break 80 | 81 | return repositories 82 | 83 | 84 | @staticmethod 85 | def get_next_page_url(headers): 86 | """ 87 | Retrieve the URL of the next page in the paginated response. 88 | 89 | Args: 90 | headers (dict): The header information of the response. 91 | 92 | Returns: 93 | str: The URL of the next page, or None if there is no next page. 94 | 95 | """ 96 | link_header = headers.get('Link') 97 | if link_header: 98 | links = link_header.split(', ') 99 | for link in links: 100 | if 'rel="next"' in link: 101 | return link[link.index('<')+1:link.index('>')] 102 | return None 103 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | blinker==1.6.2 2 | certifi==2023.5.7 3 | charset-normalizer==3.1.0 4 | click==8.1.3 5 | Flask==2.3.2 6 | gunicorn==20.1.0 7 | idna==3.4 8 | itsdangerous==2.1.2 9 | Jinja2==3.1.2 10 | MarkupSafe==2.1.3 11 | requests==2.31.0 12 | urllib3==2.0.3 13 | Werkzeug==2.3.6 14 | -------------------------------------------------------------------------------- /routes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/routes/__init__.py -------------------------------------------------------------------------------- /routes/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/routes/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /routes/__pycache__/index.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/routes/__pycache__/index.cpython-311.pyc -------------------------------------------------------------------------------- /routes/index.py: -------------------------------------------------------------------------------- 1 | """ 2 | routes/index.py 3 | 4 | This module defines the routes for the Flask application. 5 | It contains routes for the index page and the search page. 6 | 7 | Routes: 8 | - index: Renders the index page. 9 | - search: Handles the search form submission and renders the result page. 10 | 11 | """ 12 | 13 | from flask import (render_template, Blueprint, request, current_app) 14 | from models.filter import Filter 15 | 16 | 17 | # create and configure the blueprint 18 | index_bp = Blueprint( 19 | 'index_bp', __name__, 20 | template_folder='templates', 21 | static_folder='static' 22 | ) 23 | # define the route path 24 | 25 | 26 | @index_bp.route('/', methods=['GET']) 27 | def index(): 28 | """ 29 | Renders the index page. 30 | 31 | Returns: 32 | The rendered index page template. 33 | """ 34 | return render_template('index.html') 35 | 36 | 37 | # route to the search page 38 | @index_bp.route('/repos/', methods=['POST']) 39 | def search(): 40 | """ 41 | Handles the search form submission and renders the result page. 42 | 43 | Returns: 44 | The rendered result page template with the search parameters and filtered repositories. 45 | """ 46 | topic = request.form.get('topic').replace(' ', '-') 47 | rating = request.form.get('rating') 48 | language = request.form.get('language') 49 | repositories = Filter.search_repositories(language, topic, rating, current_app.config['TOKEN']) 50 | filtered_repos = [] 51 | if repositories is not None: 52 | for repo in repositories: 53 | # if repo['stargazers_count'] >= int(rating): 54 | filtered_repos.append(repo) 55 | 56 | # Redirect to the result page with search parameters as query parameters 57 | return render_template('result.html', topic=topic, rating=rating, repositories=filtered_repos) 58 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | config.py 3 | 4 | This module contains the configuration settings for the application. 5 | 6 | Attributes: 7 | - SECRET_KEY: A random string used for cryptographic purposes. 8 | - basedir: The absolute path of the directory where the script runs. 9 | - DEBUG: A boolean value indicating whether debug mode is enabled. 10 | - TOKEN: The token used for authentication. 11 | 12 | Usage: 13 | - Import the Config class from this module to access the configuration settings. 14 | - Modify the attributes of the Config class to customize the application's behavior. 15 | """ 16 | import os 17 | 18 | # pylint: disable=too-few-public-methods 19 | class Config: 20 | """ 21 | Configuration class for the application. 22 | 23 | This class holds the configuration settings for the application, 24 | such as the secret key, base directory, debug mode, and token. 25 | 26 | Attributes: 27 | SECRET_KEY (str): A secret key for the application. 28 | basedir (str): The absolute path of the directory where the script runs. 29 | DEBUG (bool): Enable or disable debug mode. 30 | TOKEN (str): The token for authentication. 31 | 32 | """ 33 | 34 | SECRET_KEY = os.urandom(32) 35 | # Grabs the folder where the script runs. 36 | basedir = os.path.abspath(os.path.dirname(__file__)) 37 | # Enable debug mode. 38 | DEBUG = True 39 | # put your token here 40 | TOKEN = "Put your token" 41 | -------------------------------------------------------------------------------- /static/favicon_io/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/favicon_io/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/android-chrome-512x512.png -------------------------------------------------------------------------------- /static/favicon_io/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/apple-touch-icon.png -------------------------------------------------------------------------------- /static/favicon_io/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon_io/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicon_io/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/favicon_io/favicon.ico -------------------------------------------------------------------------------- /static/favicon_io/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /static/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/images/1.png -------------------------------------------------------------------------------- /static/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/images/2.png -------------------------------------------------------------------------------- /static/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epythonlab/github-search-tool/a5c0d93816e404dad158d9c32aa0b2d86997c634/static/images/3.png -------------------------------------------------------------------------------- /static/script.js: -------------------------------------------------------------------------------- 1 | // Add JavaScript/jQuery code to show/hide the waiting message when the button is clicked 2 | document.getElementById('search-button').addEventListener('click', function() { 3 | var waitingMessage = document.getElementById('waiting-message'); 4 | // hide the button when the loading button is shown 5 | let btn = document.getElementById('search-button'); 6 | btn.style.display = 'none'; 7 | // visible the waiting message while the button is clicked on 8 | waitingMessage.style.display = 'block'; // Show the waiting message 9 | 10 | 11 | // Simulate a delay to mimic network request 12 | setTimeout(function() { 13 | waitingMessage.style.display = 'none'; // Hide the waiting message 14 | }, 3000 * 3000 * 3000 * 3000); // 3 seconds delay (adjust as needed) 15 | }); 16 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | /* CSS styles for the search container */ 2 | body{ 3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | font-size: 16px; 5 | line-height: 1.5; 6 | background-color: #222 !important; 7 | color: #fff !important; 8 | } 9 | 10 | .container { 11 | margin: 20px auto; 12 | padding: 20px; 13 | background-color: #222; 14 | padding-bottom: 60px; /* Adjust the value as needed */ 15 | } 16 | 17 | .search-container { 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | margin-top: 20px; 22 | text-align: center; 23 | 24 | } 25 | 26 | .mobile-header { 27 | margin-bottom: 20px; 28 | color: #fff; 29 | } 30 | 31 | .search-bar { 32 | display: flex; 33 | align-items: center; 34 | justify-content: center; 35 | margin-bottom: 20px; 36 | } 37 | 38 | .search-bar label { 39 | margin-right: 10px; 40 | 41 | } 42 | 43 | .search-button-container { 44 | margin-top: 16px; 45 | } 46 | 47 | .search-button { 48 | padding: 8px 16px; 49 | background-color: #007bff; 50 | color: white; 51 | border: none; 52 | border-radius: 4px; 53 | font-size: 16px; 54 | cursor: pointer; 55 | transition: background-color 0.3s ease; 56 | } 57 | 58 | .search-button:hover { 59 | background-color: #45a049; 60 | } 61 | 62 | .dropdown-container { 63 | display: flex; 64 | justify-content: center; 65 | align-items: center; 66 | } 67 | 68 | .filter-dropdown { 69 | margin: 0 10px; 70 | } 71 | 72 | .filter-dropdown label { 73 | display: block; 74 | margin-bottom: 4px; 75 | color: #fff; 76 | } 77 | 78 | .filter-dropdown select { 79 | padding: 8px; 80 | border: 1px solid #ccc; 81 | border-radius: 4px; 82 | font-size: 16px; 83 | background-color: #222; 84 | color: #fff; 85 | } 86 | 87 | 88 | /* Style for table responsive layout */ 89 | .table-responsive { 90 | margin-bottom: 20px; 91 | } 92 | 93 | @media screen and (max-width: 600px) { 94 | .table-responsive { 95 | overflow-x: auto; 96 | } 97 | 98 | } 99 | /* Custom CSS */ 100 | /* Custom CSS */ 101 | @media (max-width: 576px) { 102 | #topic-dropdown { 103 | width: 100%; 104 | max-width: 100%; 105 | } 106 | 107 | #topic-dropdown option { 108 | width: 100%; 109 | } 110 | } 111 | 112 | .search-button-container { 113 | margin-top: 16px; 114 | } 115 | 116 | .search-button { 117 | /* Your existing styles for the search button */ 118 | height: 40px; 119 | width: auto; 120 | padding: 0 20px; 121 | } 122 | .container { 123 | /* Add your container styles here */ 124 | } 125 | 126 | /* css loading while button is click on */ 127 | /* Add the CSS styles for the waiting message here */ 128 | .waiting-message { 129 | display: none; /* Initially hide the waiting message */ 130 | color: #ffffff; 131 | background-color: rgba(0, 0, 0, 0.8); 132 | padding: 10px; 133 | border-radius: 5px; 134 | position: fixed; 135 | top: 60%; 136 | left: 50%; 137 | transform: translate(-50%, -50%); 138 | } 139 | 140 | .waiting-spinner { 141 | display: inline-block; 142 | width: 30px; 143 | height: 30px; 144 | border: 3px solid #ffffff; 145 | border-top-color: #3498db; 146 | border-radius: 50%; 147 | animation: spin 1s infinite linear; 148 | } 149 | 150 | @keyframes spin { 151 | 0% { transform: rotate(0deg); } 152 | 100% { transform: rotate(360deg); } 153 | } 154 | 155 | /* github search tool icon generator */ 156 | .icon-github-search { 157 | display: inline-block; 158 | width: 40px; 159 | height: 40px; 160 | background-color: #007bff; 161 | border-radius: 50%; 162 | position: relative; 163 | overflow: hidden; 164 | } 165 | 166 | .icon-github-search::before, 167 | .icon-github-search::after { 168 | content: ""; 169 | display: block; 170 | position: absolute; 171 | } 172 | 173 | .icon-github-search::before { 174 | top: 50%; 175 | left: 50%; 176 | transform: translate(-50%, -50%); 177 | width: 16px; 178 | height: 16px; 179 | background-color: #fff; 180 | border-radius: 50%; 181 | } 182 | 183 | .icon-github-search::after { 184 | top: 50%; 185 | left: 0; 186 | transform: translate(0, -50%); 187 | width: 100%; 188 | height: 2px; 189 | background-color: #fff; 190 | } 191 | 192 | .icon-github-search::before, 193 | .icon-github-search::after { 194 | transition: background-color 0.3s; 195 | } 196 | 197 | .icon-github-search:hover::before, 198 | .icon-github-search:hover::after { 199 | background-color: #f0f0f0; 200 | } 201 | 202 | 203 | 204 | .footer { 205 | background-color: #333; 206 | color: #fff; 207 | padding: 10px; 208 | text-align: center; 209 | position: fixed; 210 | left: 0; 211 | bottom: 0; 212 | width: 100%; 213 | } 214 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {% block title %}{% endblock title %} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% block body %} 23 | 24 | 25 | {% endblock body %} 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends 'base.html' %} 3 | {% block title %} Github Search Tool {% endblock title %} 4 | {% block body %} 5 |
6 |
7 |
8 |
9 | 10 | 11 |

GitHub Repo Search

12 |
13 |
14 |
15 |
16 | 17 | 18 |
19 |
20 |
21 | 22 |
23 |
24 |
25 | 26 | 35 |
36 |
37 |
38 |
39 | 40 | 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | 56 |
57 |
58 |

Please wait...

59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 |
67 |
68 | 69 | 70 | 71 | 74 | 75 | 76 | 77 | {% endblock body%} 78 | -------------------------------------------------------------------------------- /templates/result.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends 'base.html' %} 3 | {% block title %} Github Search Tool {% endblock title %} 4 | {% block body %} 5 | 6 | 7 |
8 |

Search Results

9 | 10 | Back to Search 11 | 12 | {% if repositories %} 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% set counter = 1 %} 27 | 28 | {% for repo in repositories %} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% set counter = counter + 1 %} 37 | 38 | 39 | {% endfor %} 40 | 41 |
#NameURLStarsForksOwner
{{loop.index}}{{ repo['name'] }}{{ repo['html_url'] }}{{ repo['stargazers_count'] }}{{ repo['forks_count'] }}{{ repo['owner']['login'] }}
42 |
43 | {% else %} 44 |

No repositories found.

45 | {% endif %} 46 | 47 |
48 | 51 | 52 | 53 | 54 | 55 | {% endblock body%} 56 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | """File name: wsgi.py 2 | run this file only 3 | Run: python3 wsgi.py on terminal 4 | - change the host in production 5 | - change the debug to False in production 6 | - change port as needed 7 | """ 8 | from app import app 9 | if __name__ == '__main__': 10 | # DEBUG is set to TRUE. Change to FALSE for production 11 | app.run(host='0.0.0.0', port=3000) 12 | --------------------------------------------------------------------------------