Skip to content

Commit

Permalink
Merge branch 'master' of github.com:MLAB-project/MLABweb
Browse files Browse the repository at this point in the history
  • Loading branch information
roman-dvorak committed Feb 21, 2024
2 parents c489b5f + 6ffe013 commit fd103b3
Show file tree
Hide file tree
Showing 13 changed files with 466 additions and 85 deletions.
57 changes: 53 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,58 @@
# MLABweb

MLAB home page with web-based tool for creating and editing of [MLAB](https://github.com/MLAB-project/Modules) modules.
MLAB home page with the interactive catalog of [MLAB modules](https://github.com/MLAB-modules).


### Required prerequisites
## Použití

sudo apt install python-tornado python-mysqldb python-requests-oauthlib
sudo pip install requests requests_oauthlib glob2 gitpython six w3lib xhtml2pdf --upgrade
Jednotlivé položky katalogu modulů jsou na webu zobrazovány na základě dvou předpokladů:
- Modul je umístěn v GitHub organizaci [MLAB-modules](https://github.com/MLAB-modules)
- Modul obsahuje yaml soubor s metadaty pro zobrazení na webu. Soubor se musí nacházet v `/doc/metadata.yaml`.

Při splnění těchto podmínek bude modul na webu automaticky zobrazen. Zobrazení nebo aktualizace dat může nějakou dobu trvat. Pokud se nic nestane do jedné hodiny od provedení úpravy, je potřeba analyzovat možné problémy popřípadě kontaktovat správce webu.


### Automatická aktualizace dat
Pro minimalizaci množství kroků potřebných pro zobrazení modulu na webu se snažíme maximum procesů automatizovat. K tomu slouží GitHub actions workflow, které jsme si naprogramovaly pro tyto účely. Actions postupy typicky aktualizujeme způsobem, že v repozitáři modulu máme submodul [/doc/assets/](https://github.com/MLAB-project/documents), který obsahuje jednotlivá actions potřebná pro správné fungování repozitáře.


### Metadata yaml

Zde je základní struktura yaml souboru.
Flag `<G:` značí, že hodnota je generovaná automaticky na základě github actions. Tato hodnota může být kdykoliv automaticky přepsána.
Flag `<U:` značí, že je to uživatelsky zadávaná hodnoda.

```
description: <G: Popis modulu, cca 250 znaků, generovaný z github popisu>
github_branch: <G: Výchozí větev na githubu>
github_branches:
- <G: Seznam větví v repozitáři>
github_repo: <G: Název repozitáře>
github_url: <G: URL adresa k repozitáři>
homepage: <U: true/false, má být modul zobrazen na úvodní stránce webu? >
image_title: <U: Jaký obrázek má být zobrazen na přehledu modulů? >
images:
- <G: Seznam obrázků v repozitáři>
issues: <G: Počet otevřených issue>
mark: <U: Hodnocení kvality modulu, číslo 0-100)
mod_ibom: <G: Cesta k ibom souboru>
mod_scheme: <G: Cesta ke schématu>
tags:
- <G: Seznam tagů, generovánoz z github toppics>
title: <G: Název modulu - generováno z názvu repozitáře>
updated: <G: čas aktualizace>
```

#### Stav a kvalita modulů
Na webu je zelený proužek a filtr, kterým lze vybírat stav modulů:
![obrazek](https://github.com/MLAB-project/MLABweb/assets/5196729/8b603185-a976-4acb-b256-cd5631cbcdd0)

To je v yaml souboru parametr 'status', který může mít hodnotu 1-5, pokud není uvedena, tak se aplikuje 2.
Hodnota 4 (replaced) se automaticky nastaví ve webserveru v případě, že součástka má nastavený atribut [replaced](https://github.com/mlab-modules/USB232R01/blob/USB232R01B/doc/metadata.yaml#L24)

Pak existuje hodonota 'mark', což by taktéž mělo odrážet stav modulu ve smyslu jak moc má dobrou dokumentaci, jak moc je ten modul kompletní. Neexistuje ale nějaký popis toho, co odpovídá jakému číslu. Je to rozsah 0-100, tuším, že ty moduly s dobrou dokumentací mají hodnocení okolo 80-90 (já tam nechávám nějakou rezervu). Zde předpokládám, že tohle číslo bude způsobovat výchozí řazení na webu.

Další parametr je ```homepage: true/false```, což způsobí, že se to zobrazí na úvodní stránce, Tam mám odhad, že by nemělo být více než cca 12 modulů.

### Kategorie
Na webu jsou zobrazeny předvybrané kategorie, které jsou provázány z github topics. Seznam kategorií, které jsou zobrazeny v horním menu je [zde](/src/MLABweb/categories.py). V souboru s metadaty to odpovídá položce `tags`.
26 changes: 23 additions & 3 deletions repository_downloader/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
from pymongo import MongoClient
import yaml
import time

# Získání proměnných z systémových proměnných
ORGANIZATION = os.environ.get('ORGANIZATION', "mlab-modules")
Expand All @@ -15,12 +16,30 @@

# Získání seznamu repozitářů organizace
def get_organization_repositories():

# Fetch repositories in paginated manner
# Determine the total number of repositories in the organization
response = requests.get(f"https://api.github.com/orgs/{github_org}")
if response.status_code != 200:
print(f"Failed to fetch organization info: {response.content}")
sys.exit(1)
total_repos = response.json().get("public_repos", 0) # Change this to 'total_repos' if you are considering private repos as well

# Calculate the number of pages needed
pages_needed = -(-total_repos // 100) # Equivalent to math.ceil(total_repos / 100)


# Fetch repositories in a paginated manner considering the total number of repositories
repositories = []
for page in range(10):
for page in range(1, pages_needed + 1):
url = f'https://api.github.com/orgs/{ORGANIZATION}/repos?per_page=100&page={page}'
print(url)
response = requests.get(url)
if response.status_code != 200:
print(f"Failed to fetch page {page}: {response.content}")
break
repositories += json.loads(response.text)
time.sleep(2)
return repositories

# Stažení repozitáře
Expand Down Expand Up @@ -72,8 +91,9 @@ def upload_to_mongodb(repositories):

data['homepage'] = data.get('homepage', False)
data['description'] = data.get('description', '')

data['status'] = 2

if not data.get('status', False):
data['status'] = 0
data['root'] = ''

data['github_raw'] = data.get("github_url", "").replace("github.com","raw.githubusercontent.com")+"/{}/".format(data.get('github_branch'))
Expand Down
81 changes: 81 additions & 0 deletions src/MLABweb/categories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
categories = [

{
'_id': 'power-sw',
'name': "Power switches",
'description': "Power switches"
},{
'_id': "sensor",
'name': "Sensors",
'description': "Sensor modules"
},{
'_id': "clock",
'name': "Clock",
},{
'_id': "comm-rf",
'name': "Radio communication",
},{
'_id': "comm-ir",
'name': "IR communication",
},{
'_id': "comm-serial",
'name': "Serial communication",
},{
'_id': "translators",
'name': "Translators",
},{
'_id': "memories",
'name': "Memories",
},{
'_id': "mcu-arm",
'name': "ARM",
},{
'_id': "mcu-avr",
'name': "AVR",
},{
'_id': "mcu-pic",
'name': "PIC",
},{
'_id': "power-supply",
'name': "Power supply",
},{
'_id': "universial",
'name': "Universial parts",
},{
'_id': "human-interface",
'name': "Human interfaces",
},{
'_id': "audio",
'name': "Audio",
},{
'_id': "motor-driver",
'name': "Motor drivers",
},{
'_id': "x86",
'name': "x86 CPU",
},{
'_id': "box",
'name': "Boxes",
},{
'_id': "op-amps",
'name': "Operational amplifiers",
},{
'_id': "tdc",
'name': "Time-to-digital converters",
},{
'_id': "measuring",
'name': "Measuring",
},{
'_id': "cpld-fpga",
'name': "CPLD FPGA",
},{
'_id': "ad-converter",
'name': "AD converters",
},{
'_id': "mechanical",
'name': "Mechanical parts",
},{
'_id': "mcu",
'name': "Microcontrollers",
}
]
28 changes: 20 additions & 8 deletions src/MLABweb/handlers/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,15 @@ def get(self, module = None):
if not module_data.get('file_readme'):
readme_html = "No content"
else:
readme_html = markdown.markdown(open(module_data.get('file_readme', ''), 'r').read(),
extensions=['pymdownx.extra', 'pymdownx.magiclink', 'pymdownx.b64'],
extension_configs={
"pymdownx.b64": {"base_path": os.path.dirname(module_data.get('file_readme', ''))},
}
)
try:
readme_html = markdown.markdown(open(module_data.get('file_readme', ''), 'r').read(),
extensions=['pymdownx.extra', 'pymdownx.magiclink', 'pymdownx.b64'],
extension_configs={
"pymdownx.b64": {"base_path": os.path.dirname(module_data.get('file_readme', ''))},
}
)
except Exception as e:
readme_html = "No README.."

self.render("modules.detail.hbs", db_web = self.db_web, module=module, module_data=module_data, images = images, documents = glob2.glob(module_path+"//**/*.pdf"),
assembly_gh_link = assembly_gh_link, readme_html = readme_html, path = module_path)
Expand Down Expand Up @@ -271,7 +274,7 @@ def get(self, category = None):
if category:
q += [
{
"$match": {'category[]': {cat_pol: [category]}}
"$match": {'tags': {cat_pol: [category]}}
}]
q += [
{
Expand Down Expand Up @@ -323,7 +326,7 @@ def post(self, category = None):
"name": { "$regex": search, "$options": 'i'}
},
{
'short_en': { "$regex": search, "$options": 'i'}
'description': { "$regex": search, "$options": 'i'}
}
]
}
Expand All @@ -342,6 +345,15 @@ def get(self):
modules = self.db_web.Modules.find().sort([(order, 1)])
self.render("modules.overview.hbs", parent=self, modules = modules)

class modules_overview_JSON(BaseHandler):
def get(self):
order = self.get_argument('order', '_id')
modules = self.db_web.Modules.find().sort([(order, 1)])
modules_list = list(modules)

self.set_header('Content-Type', 'application/json')
self.write(json.dumps(modules_list, indent=2))

class moduleImageUpload(BaseHandler):
'''
Tato funkce se stara o prijem uploadovanych obrazku a spravne zarazeni.
Expand Down
11 changes: 11 additions & 0 deletions src/MLABweb/mlab_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

from handlers import github, admin, auth, api
from handlers import _sql, BaseHandler
import pymongo

from categories import categories

tornado.options.define("port", default=5000, help="port", type=int)
tornado.options.define("debug", default=False, help="debug mode")
Expand Down Expand Up @@ -60,6 +63,7 @@ def __init__(self, config={}):
(r'/module/(.*)/', admin.module_detail),
(r'/module/(.*)', admin.module_detail),
(r'/modules/all', admin.modules_overview),
(r'/modules/all/json', admin.modules_overview_JSON),

(r'/api/modules/', api.modules),
(r'/api/module/(.*)/', api.module),
Expand Down Expand Up @@ -117,6 +121,13 @@ def __init__(self, config={}):
autoreload=True
)
tornado.locale.load_translations("locale/")

dbw = pymongo.MongoClient('mongo', 27017).MLABweb.Category
dbw.delete_many({})
dbw.insert_many(categories)



tornado.web.Application.__init__(self, handlers, **settings)

def main():
Expand Down
10 changes: 5 additions & 5 deletions src/MLABweb/static/mlab_style.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,22 @@ width: 100%;
}

.status-0{
background-color: #d7ccc8;
background-color: #d7ccc8 !important;
}
.status-1{
background-color: #ffeb3b;
background-color: #ffeb3b !important;
}

.status-2{
background-color: #8bc34a;
background-color: #8bc34a !important;
}

.status-3{
background-color: #ffc107;
background-color: #ffc107 !important;
}

.status-4{
background-color: #f44336;
background-color: #f44336 !important;
}

.carousel-header{
Expand Down
14 changes: 7 additions & 7 deletions src/MLABweb/template/base.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@

</div></body>

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-105355821-1"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-105355821-1', 'auto');
ga('send', 'pageview');
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-105355821-1');
</script>

</html>

4 changes: 2 additions & 2 deletions src/MLABweb/template/modules.detail.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
<meta name="robots" content="index,follow">
<meta name="author" content="MLAB team <[email protected]>">
<link rel="canonical" href="https://www.mlab.cz/module/{{module_data['name']}}/">

<meta name="thumbnail" content="{{module_data['github_raw']}}/{{module_data.get('image_title')}}" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"description": "{{module_data['description']}}",
"name": "{{module_data['name']}}",
"image": "{{module_data['github_raw']}}/{{module_data['image_title']}}",
"image": "{{module_data['github_raw']}}/{{module_data.get('image_title')}}",
"brand": "MLAB.cz",
"manufacturer": "www.ust.cz",
"url": "https://www.mlab.cz/module/{{module_data['name']}}/"
Expand Down
13 changes: 7 additions & 6 deletions src/MLABweb/template/modules.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ a.selected{
</style>

{%if current_user and current_user['is_staff'] %}
<a href="/modules/all">Modules overview</a>
<a href="/module/new">New module</a>
{%end%}


<div class="card">
Expand All @@ -63,7 +59,7 @@ a.selected{
<div class="mb-3">
<div class="row mb-2">
<div>
<span class="checkbox mr-5"><label><input type="checkbox" name="status" onchange="reload()" value="0" {% if status and 0 in status %} checked {%end%}><span class="status status-0" style="width: 0.75em; display: inline-block;border: solid 1px; margin-left: 7px;"></span> Proposial </label></span>
<span class="checkbox mr-5"><label><input type="checkbox" name="status" onchange="reload()" value="0" {% if status and 0 in status %} checked {%end%}><span class="status status-0" style="width: 0.75em; display: inline-block;border: solid 1px; margin-left: 7px;"></span> Proposal </label></span>
<span class="checkbox mr-5"><label><input type="checkbox" name="status" onchange="reload()" value="1" {% if status and 1 in status %} checked {%end%}><span class="status status-1" style="width: 0.75em; display: inline-block;border: solid 1px; margin-left: 7px;"></span> In development</label></span>
<span class="checkbox mr-5"><label><input type="checkbox" name="status" onchange="reload()" value="2" {% if status and 2 in status %} checked {%end%}><span class="status status-2" style="width: 0.75em; display: inline-block;border: solid 1px; margin-left: 7px;"></span> Production</label></span>
<span class="checkbox mr-5"><label><input type="checkbox" name="status" onchange="reload()" value="3" {% if status and 3 in status %} checked {%end%}><span class="status status-3" style="width: 0.75em; display: inline-block;border: solid 1px; margin-left: 7px;"></span> Replaced</label></span>
Expand Down Expand Up @@ -91,6 +87,11 @@ a.selected{
<div class="row m-0">
<div class=" cantainer card-deck row" id="modules_box">

{% if not modules %}
<h2>:-( No module with this filter was found... Try to search differently. Or it is also possible that this module has not yet propagated this module and you can be the first to do it.
</h2>
{% end %}

{% for module in modules %}


Expand All @@ -100,7 +101,7 @@ a.selected{
<a href="/module/{{module['_id']}}/" target="_blank">

{% if module.get('image_title') %}
<img class="card-img-top" style="max-height: 250pt; object-fit: cover;"src="/static/loading.png" data-src="{{module['github_raw']}}/{{module['image_title']}}" alt="{{module['_id']}}">
<img class="card-img-top" style="max-height: 250pt; object-fit: cover;"src="/static/loading.png" data-src="{{module['github_raw']}}/{{module.get('image_title')}}" alt="{{module['_id']}}">
{% else %}
<img class="card-img-top" style="max-height: 250pt; object-fit: cover;" src="/static/noimage.png" alt="Module">
{% end %}
Expand Down
Loading

0 comments on commit fd103b3

Please sign in to comment.