Răsfoiți Sursa

Add sponsor section to website (#3906)

This PR adds a section with our top sponsors.
Falko Schindler 6 luni în urmă
părinte
comite
1e9a35b272
5 a modificat fișierele cu 161 adăugiri și 2 ștergeri
  1. 6 2
      README.md
  2. 118 0
      fetch_sponsors.py
  3. 29 0
      website/main_page.py
  4. 7 0
      website/sponsors.json
  5. 1 0
      website/sponsors.py

+ 6 - 2
README.md

@@ -109,10 +109,14 @@ because of their great performance and ease of use.
 Maintenance of this project is made possible by all the [contributors](https://github.com/zauberzeug/nicegui/graphs/contributors) and [sponsors](https://github.com/sponsors/zauberzeug).
 If you would like to support this project and have your avatar or company logo appear below, please [sponsor us](https://github.com/sponsors/zauberzeug). 💖
 
+<!-- SPONSORS -->
 <p align="center">
-   <a href="https://github.com/lechler-gmbh"><img src="https://github.com/lechler-gmbh.png" width="50px" alt="Lechler GmbH" /></a>
-   <a href="https://github.com/daviborges666"><img src="https://github.com/daviborges666.png" width="50px"alt="daviborges666" /></a>
+  <a href="https://github.com/lechler-gmbh"><img src="https://github.com/lechler-gmbh.png" width="50px" alt="Lechler GmbH" /></a>
+  <a href="https://github.com/Zhifeng2019"><img src="https://github.com/Zhifeng2019.png" width="50px" alt="Zhifeng" /></a>
+  <a href="https://github.com/sereneturtlefox"><img src="https://github.com/sereneturtlefox.png" width="50px" alt="None" /></a>
+  <a href="https://github.com/daviborges666"><img src="https://github.com/daviborges666.png" width="50px" alt="Davi Borges" /></a>
 </p>
+<!-- SPONSORS -->
 
 Consider this low-barrier form of contribution yourself.
 Your [support](https://github.com/sponsors/zauberzeug) is much appreciated.

+ 118 - 0
fetch_sponsors.py

@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+import json
+import os
+import re
+from pathlib import Path
+
+import requests
+
+# NOTE:
+# requires a GitHub token with the necessary permissions read:org and read:user
+# call with `GITHUB_TOKEN=ghp_XXX ./fetch_sponsors.py`
+
+
+response = requests.post(
+    'https://api.github.com/graphql',
+    json={
+        'query': '''
+            query($organization: String!) {
+                organization(login: $organization) {
+                    sponsorshipsAsMaintainer(first: 100, includePrivate: true) {
+                        nodes {
+                            sponsorEntity {
+                                ... on User {
+                                    login
+                                    name
+                                    url
+                                    avatarUrl
+                                }
+                                ... on Organization {
+                                    login
+                                    name
+                                    url
+                                    avatarUrl
+                                }
+                            }
+                            tier {
+                                monthlyPriceInDollars
+                                name
+                                isOneTime
+                            }
+                            createdAt
+                        }
+                    }
+                }
+            }
+        ''',
+        'variables': {'organization': 'zauberzeug'},
+    },
+    headers={
+        'Authorization': f'token {os.getenv("GITHUB_TOKEN")}',
+        'Accept': 'application/vnd.github.v3+json'
+    },
+    timeout=10.0,
+)
+response.raise_for_status()
+data = response.json()
+if 'errors' in data:
+    raise RuntimeError(f'GitHub API Error: {data["errors"]}')
+
+sponsors = []
+for sponsor in data['data']['organization']['sponsorshipsAsMaintainer']['nodes']:
+    sponsor_entity = sponsor['sponsorEntity']
+    tier = sponsor['tier']
+    sponsors.append({
+        'login': sponsor_entity['login'],
+        'name': sponsor_entity['name'],
+        'url': sponsor_entity['url'],
+        'avatar_url': sponsor_entity['avatarUrl'],
+        'tier_name': tier['name'],
+        'tier_amount': tier['monthlyPriceInDollars'],
+        'tier_is_one_time': tier['isOneTime'],
+        'created_at': sponsor['createdAt'],
+    })
+sponsors.sort(key=lambda s: s['created_at'])
+
+contributors = []
+page = 1
+while True:
+    contributors_response = requests.get(
+        f'https://api.github.com/repos/zauberzeug/nicegui/contributors?page={page}&per_page=100',
+        headers={
+            'Authorization': f'token {os.getenv("GITHUB_TOKEN")}',
+            'Accept': 'application/vnd.github.v3+json'
+        },
+        timeout=10.0,
+    )
+    contributors_response.raise_for_status()
+    page_contributors = contributors_response.json()
+    if not page_contributors:
+        break
+    contributors.extend(page_contributors)
+    page += 1
+
+print(f'Found {len(sponsors)} sponsors')
+print(f'Total contributors for NiceGUI: {len(contributors)}')
+
+Path('website/sponsors.json').write_text(json.dumps({
+    'top': [s['login'] for s in sponsors if s['tier_amount'] >= 100 and not s['tier_is_one_time']],
+    'total': len(sponsors),
+    'contributors': len(contributors),
+}, indent=2) + '\n')
+
+sponsor_html = '<p align="center">\n'
+for sponsor in sponsors:
+    if sponsor['tier_amount'] >= 25 and not sponsor['tier_is_one_time']:
+        sponsor_html += f'  <a href="{sponsor["url"]}"><img src="{sponsor["url"]}.png" width="50px" alt="{sponsor["name"]}" /></a>\n'
+sponsor_html += '</p>'
+readme_path = Path('README.md')
+readme_content = readme_path.read_text()
+updated_content = re.sub(
+    r'<!-- SPONSORS -->.*?<!-- SPONSORS -->',
+    f'<!-- SPONSORS -->\n{sponsor_html}\n<!-- SPONSORS -->',
+    readme_content,
+    flags=re.DOTALL,
+)
+readme_path.write_text(updated_content)
+
+print('README.md and sponsors.json updated successfully.')

+ 29 - 0
website/main_page.py

@@ -1,3 +1,6 @@
+import json
+from pathlib import Path
+
 from nicegui import ui
 
 from . import documentation, example_card, svg
@@ -5,6 +8,8 @@ from .examples import examples
 from .header import add_head_html, add_header
 from .style import example_link, features, heading, link_target, section_heading, subtitle, title
 
+SPONSORS = json.loads((Path(__file__).parent / 'sponsors.json').read_text())
+
 
 def create() -> None:
     """Create the content of the main page."""
@@ -159,6 +164,30 @@ def create() -> None:
             for example in examples:
                 example_link(example)
 
+    with ui.column().classes('dark-box p-8 lg:p-16 my-16 bg-transparent border-y-2'):
+        with ui.column().classes('mx-auto items-center gap-y-8 gap-x-32 lg:flex-row'):
+            with ui.column().classes('max-lg:items-center max-lg:text-center'):
+                ui.markdown('NiceGUI is supported by') \
+                    .classes('text-2xl md:text-3xl font-medium')
+                with ui.row(align_items='center'):
+                    assert SPONSORS['total'] > 0
+                    ui.markdown(f'''
+                        our top {'sponsor' if SPONSORS['total'] == 1 else 'sponsors'}
+                    ''')
+                    for sponsor in SPONSORS['top']:
+                        with ui.link(target=f'https://github.com/{sponsor}').classes('row items-center gap-2'):
+                            ui.image(f'https://github.com/{sponsor}.png').classes('w-12 h-12 border')
+                            ui.label(f'@{sponsor}')
+                ui.markdown(f'''
+                    as well as {SPONSORS['total'] - len(SPONSORS['top'])} other [sponsors](https://github.com/sponsors/zauberzeug)
+                    and {SPONSORS['contributors']} [contributors](https://github.com/zauberzeug/nicegui/graphs/contributors).
+                ''').classes('bold-links arrow-links')
+            with ui.link(target='https://github.com/sponsors/zauberzeug').style('color: black !important') \
+                    .classes('rounded-full mx-auto px-12 py-2 border-2 border-[#3e6a94] font-medium text-lg md:text-xl'):
+                with ui.row().classes('items-center gap-4'):
+                    ui.icon('sym_o_favorite', color='#3e6a94')
+                    ui.label('Become a sponsor').classes('text-[#3e6a94]')
+
     with ui.row().classes('dark-box min-h-screen mt-16'):
         link_target('why')
         with ui.column().classes('''

+ 7 - 0
website/sponsors.json

@@ -0,0 +1,7 @@
+{
+  "top": [
+    "daviborges666"
+  ],
+  "total": 18,
+  "contributors": 125
+}

+ 1 - 0
website/sponsors.py

@@ -0,0 +1 @@
+NUM_SPONSORS = 18