diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38584e3..43529d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,80 +7,145 @@ on: branches: [master] permissions: - contents: read + contents: write pages: write deployments: write id-token: write jobs: - convert_and_release: - name: Convert CSV to files + convert_to_json: + name: Convert CSV to JSON files + runs-on: ubuntu-latest + steps: + - name: checkout repo content + uses: actions/checkout@v2 # checkout the repository content to github runner. + + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: "3.10" + + - name: execute py script # run the run.py to get the latest data + run: | + python convertors/json_convertor.py + + - name: Upload converted files # Upload 3 JSON files outputted from py script + uses: actions/upload-artifact@v1 + with: + name: json + path: ./out + + convert_to_html: + name: Convert CSV to HTML template runs-on: ubuntu-latest - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} steps: - name: checkout repo content uses: actions/checkout@v2 # checkout the repository content to github runner. + - name: setup python uses: actions/setup-python@v2 with: python-version: "3.10" + + - name: Install Jinja2 # For putting data into HTML template + run: | + pip install Jinja2 + - name: execute py script # run the run.py to get the latest data run: | - python convertors/convertor.py - - # - name: Get current date - # id: date - # run: echo "::set-output name=date::$(date +'%Y%m%d-%H%M')" - # - name: Release - # uses: actions/create-release@v1 - # id: create_release - # with: - # draft: false - # prerelease: false - # release_name: ${{ steps.date.outputs.date }} - # tag_name: ${{ steps.date.outputs.date }} - # body: "Expanded drone manufacturer and drone models database" - # env: - # GITHUB_TOKEN: ${{ github.token }} - - # - name: Upload manufacturers artifact - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ github.token }} - # with: - # upload_url: ${{ steps.create_release.outputs.upload_url }} - # asset_path: ./out/manufacturers.json - # asset_name: manufacturers.json - # asset_content_type: application/json - - # - name: Upload manufacturers with models artifacts - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ github.token }} - # with: - # upload_url: ${{ steps.create_release.outputs.upload_url }} - # asset_path: ./out/manufacturersWithModels.json - # asset_name: manufacturersWithModels.json - # asset_content_type: application/json - - # - name: Upload models artifacts - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ github.token }} - # with: - # upload_url: ${{ steps.create_release.outputs.upload_url }} - # asset_path: ./out/models.json - # asset_name: models.json - # asset_content_type: application/json + python convertors/html_convertor.py + - name: Upload converted files # Upload html and CSS + fonts outputted from py script + uses: actions/upload-artifact@v1 + with: + name: html + path: ./out + + release: + name: Create a release + needs: [convert_to_html, convert_to_json] + runs-on: ubuntu-latest + steps: + - name: Download JSON artifact + uses: actions/download-artifact@v3 + with: + name: json + path: ./json + + - name: Get current date # Get formatted date for release tag creation + id: date + run: echo "::set-output name=date::$(date +'%Y%m%d-%H%M')" + + - name: Release # Create a release + uses: actions/create-release@v1 + id: create_release + with: + draft: false + prerelease: false + release_name: ${{ steps.date.outputs.date }} + tag_name: ${{ steps.date.outputs.date }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload manufacturers artifact # Attach manufacturers JSON to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./json/manufacturers.json + asset_name: manufacturers.json + asset_content_type: application/json + + - name: Upload manufacturers with models artifacts # Attach manufacturers with models JSON to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./json/manufacturersWithModels.json + asset_name: manufacturersWithModels.json + asset_content_type: application/json + + - name: Upload models artifacts # Attach models JSON to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./json/models.json + asset_name: models.json + asset_content_type: application/json + + deploy: + name: Deploy to Github pages + needs: [convert_to_html, convert_to_json] + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Download JSON artifact # Download JSON out file + uses: actions/download-artifact@v3 + with: + name: json + path: ./json + - name: Download HTML artifact # Download HTML out file + uses: actions/download-artifact@v3 + with: + name: html + path: ./html + - name: Merge artifacts for upload # Merging the two artifacts into one, which is then uploaded to pages + run: | + mkdir out + cp -a ./json/. ./out/ + cp -a ./html/. ./out/ - name: Upload converted files uses: actions/upload-pages-artifact@v0.1.0 with: name: github-pages path: ./out - - name: Deploy Github Pages + - name: Deploy Github Pages # Deploy to pages uses: actions/deploy-pages@v1 id: deployment with: diff --git a/README.md b/README.md index af6bfb2..8420892 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,50 @@ -# opendronelist +# OpenDroneList -Opendronelist is a public open-source community-driven list of drones and their common properties. +OpenDroneList is a public open-source community-driven list of drones and their common properties. -## What is **opendronelist** good for? +## What is **OpenDroneList** good for? Thanks to various output formats, including the human-readable HTML table, or computer-readable CSV, JSONs and others, the list can be used for developing your own applications or to use for your data analysis or other projects. We, [authors](https://dronetag.cz), use opendronelist in many systems and user interfaces requiring the same or similar data — for example when you pick pre-defined drone in our mobile app or when using [Dronald](https://dronald.cz), we always query the latest data from the opendronelist to show a list of known drones and their properties. -## Available properties - -* Drone model/product name, vendor -* Drone weight -* Drone endurance - * Used for authoritative processes in U-space -* Year of manufacture (?) -* TODO +## Currently available properties + +- **Manufacturer & Model Name** + - The commercial name of the drone +- **Class** + - UAV Class label designated for the drone (labels such as C0, C1, ...) +- **Weight** + - The nominal weight of the drone from the manufacturer specifications + - in grams +- **Max. takeoff weight** + - The maximum allowed takeoff weight of the drone + - Usually used to determine the drone's weight category + - in grams +- **Endurance** + - The nominal maximum flight time of the drone + - in minutes +- **Has Camera?** + - Determines if the drone is equipped with a camera +- **Is Toy?** + - Determines if the drone is classified as a toy + - Drones are regarded as a toy if the drone documentation allows the use of the drone for children below 14 years of age according to Directive 2009/48/ES ## Formats available -The list is avilable in CSV file which is then converted into three JSON files - found [here](https://github.com/dronetag/opendronelist/releases/latest) +The list is avilable in following output formats: + +- [CSV Format](./list.csv) +- JSON Format + - Manufacturers + - Isolated array of unique manufacturers specified in the CSV + - Download [here](https://github.com/dronetag/opendronelist/releases/latest/download/manufacturers.json) + - Models + - An array of models, with data about the models - (manufacturer, name, weight, ...) + - Download [here](https://github.com/dronetag/opendronelist/releases/latest/download/models.json) + - Manufacturers with Models + - An array of unique manufacturers and all of their models which are specified in the CSV + - Download [here](https://github.com/dronetag/opendronelist/releases/latest/download/manufacturersWithModels.json) ## Guaranties & Liability diff --git a/convertors/html_convertor.py b/convertors/html_convertor.py new file mode 100644 index 0000000..50d6eb4 --- /dev/null +++ b/convertors/html_convertor.py @@ -0,0 +1,56 @@ +import csv +import os +from jinja2 import Environment, PackageLoader +import shutil + +env = Environment(loader=PackageLoader('html_convertor', 'templates')) + +template = env.get_template("template.html.jinja") + +dir_path = 'out' + +os.makedirs(dir_path, exist_ok=True) +with open('list.csv') as csv_file: + # Read csv - maybe input as a arg + csv_reader = csv.reader(csv_file, delimiter=',') + line_count = 0 # For iterating through lines + manufacturers = dict() # Initialize manufacturers as a Dict + models = list() # Initialize models as a list + parameters = dict() # Initialize parameters as a dict + + for row in csv_reader: + for param in row: # only first row with parameters is necessary + parameters[param] = row.index(param) + break + + # Reset for second iteration + line_count = 0 + csv_file.seek(0) + + # Second iteration of CSV for two JSON + for row in csv_reader: + if line_count == 0: + line_count += 1 + continue + + manufacturer = row[parameters.get('manufacturer')] + name = row[parameters.get('name')] + uas_class = row[parameters.get('class')] + weight = row[parameters.get('weight')] + max_takeoff = row[parameters.get('max_takeoff')] + endurance = row[parameters.get('endurance')] + has_camera = row[parameters.get('has_camera')] + is_toy = row[parameters.get('is_toy')] + + models.append({'manufacturer': manufacturer, 'name': name, 'uas_class': uas_class, + "weight": weight, 'max_takeoff': max_takeoff, 'endurance': endurance, 'has_camera': has_camera, 'is_toy': is_toy}) + + line_count += 1 + + with open(os.path.join(dir_path, 'index.html'), 'w') as outfile: + outfile.write(template.render(models=models)) + try: # throws an error of file being in the folder, even in case of empty folder, nevertheless, the files are copied + shutil.copy('templates/styles.css', 'out/styles.css') + shutil.copytree('templates/fonts', 'out/fonts') + except: + pass diff --git a/convertors/convertor.py b/convertors/json_convertor.py similarity index 100% rename from convertors/convertor.py rename to convertors/json_convertor.py diff --git a/convertors/templates/template.html.jinja b/convertors/templates/template.html.jinja new file mode 100644 index 0000000..ded4af3 --- /dev/null +++ b/convertors/templates/template.html.jinja @@ -0,0 +1,85 @@ + + + + + + + OpenDroneList + + + +
+

OpenDroneList

+ +

Open-source list of drones and their properties

+ +

+ View or edit on GitHub +

+ +

Available in various formats:

+ +
+ + +
+ + + + + + + + + + + + + + + + + {% for model in models %} + + + + + + + + + + + {% endfor %} + +
Manufacturer Name Class Weight (grams) Max Takeoff (grams) Endurance (minutes) Has Camera Is Toy
{{model.manufacturer}}{{model.name}}{{model.uas_class}}{{model.weight}}{{model.max_takeoff}}{{model.endurance}}{{model.has_camera}}{{model.is_toy}}
+ + +
+ + \ No newline at end of file diff --git a/templates/fonts/icomoon.eot b/templates/fonts/icomoon.eot new file mode 100644 index 0000000..85518b6 Binary files /dev/null and b/templates/fonts/icomoon.eot differ diff --git a/templates/fonts/icomoon.svg b/templates/fonts/icomoon.svg new file mode 100644 index 0000000..82d539a --- /dev/null +++ b/templates/fonts/icomoon.svg @@ -0,0 +1,17 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/fonts/icomoon.ttf b/templates/fonts/icomoon.ttf new file mode 100644 index 0000000..5f15437 Binary files /dev/null and b/templates/fonts/icomoon.ttf differ diff --git a/templates/fonts/icomoon.woff b/templates/fonts/icomoon.woff new file mode 100644 index 0000000..f681aee Binary files /dev/null and b/templates/fonts/icomoon.woff differ diff --git a/templates/styles.css b/templates/styles.css new file mode 100644 index 0000000..053382d --- /dev/null +++ b/templates/styles.css @@ -0,0 +1,119 @@ +@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:wght@200;400;700&display=swap'); + + +@font-face { + font-family: 'icomoon'; + src: url('fonts/icomoon.eot?ozqjrw'); + src: url('fonts/icomoon.eot?ozqjrw#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?ozqjrw') format('truetype'), + url('fonts/icomoon.woff?ozqjrw') format('woff'), + url('fonts/icomoon.svg?ozqjrw#icomoon') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +html { + font: 400 16px/1.2em 'Titillium Web', sans-serif; +} + +a { + color: #0868B7; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +main { + max-width: 1200px; + margin: auto; + padding: 2rem 1rem; +} + +h1 { + font-size: 3rem; + font-weight: 200; +} + +footer { + margin: 2rem 0; + padding: 2rem 0; + border-top: thin solid #d0d7de; +} + +main table { + margin: 2rem 0; + width: 100%; +} + +table, table td, table th { + border: thin solid #d0d7de; + border-collapse: collapse; + padding: 0.3em 0.6em; + font-size: 14px; +} + +table th { + text-align: left; + background: #f6f8fa; +} + +table th .icon-info { + margin-left: 0.5em; + color: #808890; +} + +.formats { + display: flex; +} + +.formats ul { + list-style: none; + margin: 0; + margin-right: 3rem; + padding: 0; +} + +.formats ul li { + margin: 0.5em 0; +} + + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-info:before { + content: "\e906"; +} +.icon-file-archive-o:before { + content: "\e902"; +} +.icon-file-code-o:before { + content: "\e903"; +} +.icon-file-excel-o1:before { + content: "\e904"; +} +.icon-file-text-o:before { + content: "\e905"; +} +.icon-file-excel-o:before { + content: "\e900"; +} +.icon-github:before { + content: "\e901"; +}