Skip to content

Redesign the dashboard #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Aug 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ef97906
init
StanFromIreland Jul 25, 2025
efd3269
Round 2
StanFromIreland Jul 25, 2025
5bf5310
Remove testing stuff
StanFromIreland Jul 25, 2025
aa30c9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
eaf4773
Clean up
StanFromIreland Jul 25, 2025
14040d8
!fixup Cleanup
StanFromIreland Jul 25, 2025
d6640d5
refactoring
StanFromIreland Jul 25, 2025
f260ff5
Little fixes
StanFromIreland Jul 25, 2025
28b557a
Fix on mobile
StanFromIreland Jul 25, 2025
f4489ed
Fixes
StanFromIreland Jul 25, 2025
12a9457
Fix metadata generation and add progress bar
StanFromIreland Jul 26, 2025
1616734
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2025
737b24d
Improve language details page
StanFromIreland Jul 26, 2025
3cd64c9
Fix json gen and minor improvements
StanFromIreland Jul 26, 2025
924fcce
Grammar
StanFromIreland Jul 26, 2025
daa0233
Decrease radius by one pixel
StanFromIreland Jul 26, 2025
116f634
Concede
StanFromIreland Jul 28, 2025
d8a16cc
Add shadow
StanFromIreland Jul 29, 2025
08ff437
Fix card link
StanFromIreland Jul 29, 2025
da07650
(Hopefully final) Review
StanFromIreland Jul 30, 2025
a3f8f17
Some changes
StanFromIreland Aug 5, 2025
c311d93
Strip everything
StanFromIreland Aug 5, 2025
133668a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 5, 2025
994c330
Fixup
StanFromIreland Aug 5, 2025
d44ef5e
HTML structure
AA-Turner Aug 6, 2025
65370ec
Update templates/index.html.jinja
AA-Turner Aug 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ jobs:
- run: sudo apt-get install -y gettext
- run: pip install -r requirements.txt
- run: uv run generate.py # generates index.html and index.json
- run: mkdir -p build && cp index.* style.css build
- name: Deploy 🚀
if: github.event_name != 'pull_request'
uses: JamesIves/github-pages-deploy-action@v4
Expand Down Expand Up @@ -55,10 +54,9 @@ jobs:
if: github.event_name == 'pull_request'
run: |
curl -Lo index.html-public https://github.com/python-docs-translations/dashboard/raw/refs/heads/gh-pages/index.html
diff --color=always -u index.html-public index.html || :
cat index.html
diff --color=always -u index.html-public build/index.html || :
cat build/index.html
- run: uv run generate_metadata.py # generates metadata.html
- run: cp metadata.html warnings* build
- name: Deploy metadata view 🚀
if: github.event_name != 'pull_request'
uses: JamesIves/github-pages-deploy-action@v4
Expand Down
24 changes: 5 additions & 19 deletions build_status.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""
Fetch build status of languages in the https://docs.python.org.
Fetch translated names of languages.

Yield a tuple of language code and a Boolean indicating
whether it is in the language switcher.
Yield a tuple of language code and a string with the translated name.
"""

import tomllib
Expand All @@ -11,26 +10,13 @@
from urllib3 import PoolManager


def get_languages(http: PoolManager) -> Iterator[tuple[str, bool]]:
def get_languages(http: PoolManager) -> Iterator[tuple[str, str]]:
data = http.request(
'GET',
'https://raw.githubusercontent.com/python/docsbuild-scripts/refs/heads/main/config.toml',
).data
config = tomllib.loads(data.decode())
for code, language in config['languages'].items():
language_code = code.lower().replace('_', '-')
in_switcher = language.get('in_prod', config['defaults']['in_prod'])
yield language_code, in_switcher


def main() -> None:
languages = {
language: in_switcher for language, in_switcher in get_languages(PoolManager())
}
print(languages)
for code in ('en', 'pl', 'ar', 'zh-cn', 'id'):
print(f'{code}: {code in languages} {languages.get(code)}')


if __name__ == '__main__':
main()
translated_name = language.get('translated_name')
yield language_code, translated_name
2 changes: 1 addition & 1 deletion build_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ def number(clones_dir: str, repo: str, language_code: str) -> int:
f'./sphinxbuild/{language_code}', # outputdir
)
)
copyfile(warning_file, f'warnings-{language_code}.txt')
copyfile(warning_file, f'build/warnings-{language_code}.txt')
return len(findall('ERROR|WARNING', Path(warning_file).read_text()))
35 changes: 23 additions & 12 deletions generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pathlib import Path

from git import Repo
from jinja2 import Template
from jinja2 import Environment, FileSystemLoader
from urllib3 import PoolManager

import build_status
Expand Down Expand Up @@ -37,7 +37,11 @@ def get_completion_progress() -> Iterator['LanguageProjectData']:
)
subprocess.run(['make', '-C', cpython_dir / 'Doc', 'venv'], check=True)
subprocess.run(['make', '-C', cpython_dir / 'Doc', 'gettext'], check=True)
languages_built = dict(build_status.get_languages(PoolManager()))

languages_built: dict[str, str] = {
language: translated_name
for language, translated_name in build_status.get_languages(PoolManager())
}

with concurrent.futures.ThreadPoolExecutor() as executor:
return executor.map(
Expand All @@ -51,7 +55,7 @@ def get_completion_progress() -> Iterator['LanguageProjectData']:
def get_project_data(
language: Language,
repo: str | None,
languages_built: dict[str, bool],
languages_built: dict[str, str],
clones_dir: str,
) -> 'LanguageProjectData':
built = language.code in languages_built
Expand All @@ -62,6 +66,7 @@ def get_project_data(
translators_data = TranslatorsData(0, False)
change = 0.0
branch = ''

return LanguageProjectData(
language,
repo,
Expand All @@ -70,7 +75,7 @@ def get_project_data(
change,
translators_data,
built,
in_switcher=languages_built.get(language.code),
translated_name=languages_built.get(language.code, ''),
uses_platform=language.code in contribute.pulling_from_transifex,
contribution_link=contribute.get_contrib_link(language.code, repo),
)
Expand All @@ -85,24 +90,30 @@ class LanguageProjectData:
change: float
translators: TranslatorsData
built: bool
in_switcher: bool | None
translated_name: str
uses_platform: bool
contribution_link: str | None


if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
logging.info(f'starting at {generation_time}')
template = Template(Path('template.html.jinja').read_text())
Path('build').mkdir(parents=True, exist_ok=True)

output = template.render(
completion_progress=(completion_progress := list(get_completion_progress())),
completion_progress = list(get_completion_progress())
counts = get_counts(Path('clones', 'cpython', 'Doc', 'build', 'gettext'))

env = Environment(loader=FileSystemLoader('templates'))
index = env.get_template('index.html.jinja').render(
completion_progress=completion_progress,
generation_time=generation_time,
duration=(datetime.now(timezone.utc) - generation_time).seconds,
counts=get_counts(Path('clones', 'cpython', 'Doc', 'build', 'gettext')),
)

Path('index.html').write_text(output)
Path('index.json').write_text(
json.dumps(completion_progress, indent=2, default=asdict)
Path('build/style.css').write_bytes(Path('src/style.css').read_bytes())
Path('build/logo.png').write_bytes(Path('src/logo.png').read_bytes())
Path('build/index.html').write_text(index)

Path('build/index.json').write_text(
json.dumps([asdict(project) for project in completion_progress], indent=2)
)
12 changes: 6 additions & 6 deletions generate_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import dacite
from git import Repo
from jinja2 import Template
from jinja2 import Environment, FileSystemLoader
from urllib3 import request

import build_warnings
Expand Down Expand Up @@ -55,20 +55,20 @@ def get_language_repo_and_completion(
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
logging.info(f'starting at {generation_time}')
template = Template(Path('metadata.html.jinja').read_text())
if (index_path := Path('index.json')).exists():
index_json = loads(Path('index.json').read_text())
env = Environment(loader=FileSystemLoader('templates'))
if (index_path := Path('build/index.json')).exists():
index_json = loads(Path('build/index.json').read_text())
else:
index_json = request('GET', argv[1]).json()

completion_progress = [
dacite.from_dict(LanguageProjectData, project) for project in index_json
]

output = template.render(
output = env.get_template('metadata.html.jinja').render(
metadata=zip(completion_progress, get_projects_metadata(completion_progress)),
generation_time=generation_time,
duration=(datetime.now(timezone.utc) - generation_time).seconds,
)

Path('metadata.html').write_text(output)
Path('build/metadata.html').write_text(output)
Binary file added src/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
121 changes: 121 additions & 0 deletions src/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* ---------------------------- Global Styles ------------------------------- */

body {
padding-top: 4.5rem;
padding-left: 1rem;
padding-right: 1rem;
padding-bottom: 3rem;
color: #5a5a5a;
background-color: rgb(245, 245, 245);
}

a {
color: #0d0d0d;
}

a:hover {
color: #1595fe;
}

/* -------------------------------- navbar ---------------------------------- */

.navbar {
background-color: rgb(245, 245, 245, 0.6);
backdrop-filter: blur(10px);
border-bottom: 0.25px solid #999;
-webkit-backdrop-filter: blur(10px);
}

.navbar li {
transition: 0.3s background-color;
text-align: center;
background-color: transparent;
padding: 0rem 1rem;
text-decoration: none;
border-radius: 0.3rem;
}

.navbar li:hover {
background-color: #d0cccd;
}

.navbar li .nav-link {
color: #0d0d0d;
}

/* ----------------------- Cards and card columns --------------------------- */

.row > [class^="col-"] {
display: flex;
}

.card {
flex: 1;
}

/* ------------------------------ Index ------------------------------------- */

.progress-bar-container {
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.2);
height: 20px;
overflow: hidden;
position: relative;
}

.progress-bar-index {
display: inline-block;
color: white;
height: 100%;
line-height: 20px;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}

/* ------------------------------ Metadata ---------------------------------- */

table {
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px 12px;
text-align: left;
white-space: nowrap;
}
th {
background-color: #d6d6d6;
}
hr {
color: #f4f4f4;
}
td[data-label="warnings"], td[data-label="lint"] {
text-align: right;
}

@media screen and (max-width: 600px) {
table, thead, tbody, th, td, tr {
display: block;
}
th {
position: absolute;
top: -9999px;
left: -9999px;
}
tr {
border: 1px solid #ccc;
margin-bottom: 5px;
}
td {
border: none;
border-bottom: 1px solid #eee;
padding-left: 50%;
position: relative;
}
td:before {
content: attr(data-label);
font-weight: bold;
left: 10px;
position: absolute;
}
}
Loading
Loading