Align profile activity and stars UI
Authored by
mfwolffe <wolffemf@dukes.jmu.edu>
- SHA
373ed2fb03f574ef0289179b5045371658c614f1- Parents
-
142e85f - Tree
21103a4
373ed2f
373ed2fb03f574ef0289179b5045371658c614f1142e85f
21103a4| Status | File | + | - |
|---|---|---|---|
| M |
docs/internal/profile.md
|
31 | 1 |
| M |
internal/web/static/css/shithub.css
|
218 | 2 |
| M |
internal/web/templates/_layout.html
|
14 | 0 |
| M |
internal/web/templates/profile/stars_tab.html
|
133 | 36 |
| M |
internal/web/templates/profile/view.html
|
40 | 9 |
docs/internal/profile.mdmodified@@ -7,8 +7,10 @@ S09 shipped the public `/{username}` page and the `/avatars/{username}` route. L | ||
| 7 | 7 | | Route | Source | Notes | |
| 8 | 8 | |---|---|---| |
| 9 | 9 | | `GET /{username}` | profile.serveProfile | Public profile. citext lookup; canonical-case 301; reserved short-circuit. | |
| 10 | +| `GET /{username}?tab=repositories` | profile.serveRepositoriesTab | Visibility-filtered user-owned repositories. | | |
| 11 | +| `GET /{username}?tab=stars` | profile.serveStarsTab | Visibility-filtered starred repositories with search, type, language, and sort controls. | | |
| 10 | 12 | | `POST /{username}/contribution-settings` | profile.contributionSettingsUpdate | Auth required. Profile owner toggles private contribution counts. | |
| 11 | -| `POST /{username}/pins` | profile.pinsUpdate | Auth required. Profile owner saves up to six public owned repositories. | | |
| 13 | +| `POST /{username}/pins` | profile.pinsUpdate | Auth required. Profile owner saves up to six public affiliated repositories. | | |
| 12 | 14 | | `GET /avatars/{username}` | profile.serveAvatar | Streams uploaded avatar OR falls back to deterministic SVG identicon. | |
| 13 | 15 | |
| 14 | 16 | `/{username}` is the **catch-all** — chi matches static routes in registration order, so the wildcard is registered last via the `ProfileMounter` hook. The reserved-name list (`internal/auth/reserved.go`) is the second line of defense if a future top-level route is added but not registered before the wildcard. |
@@ -106,6 +108,34 @@ The overview contribution calendar is computed from local Git history: | ||
| 106 | 108 | - Arbitrary public repositories outside the user's affiliation remain verified-email-only to avoid spoofed username/display-name commits. |
| 107 | 109 | - Private repositories are excluded by default. When the profile owner enables "Private contributions", private user-owned and member-org repositories contribute to the aggregate graph counts, but repository names and commit metadata are not exposed. |
| 108 | 110 | |
| 111 | +The "Contribution activity" timeline below the graph reuses the same | |
| 112 | +visibility gates: | |
| 113 | + | |
| 114 | +- Commit rows are grouped by month and repository, with private repository | |
| 115 | + names collapsed to "Private repositories". | |
| 116 | +- Public user-owned repositories created during the selected contribution | |
| 117 | + window are shown as "Created repositories" entries. | |
| 118 | +- Issues and pull requests authored by the profile user are loaded through | |
| 119 | + the issues sqlc package and then post-filtered with `policy.IsVisibleTo` | |
| 120 | + before rendering. PR rows distinguish open, closed, and merged counts. | |
| 121 | +- The first month is shown initially; the "Show more activity" button expands | |
| 122 | + older months in place without another request. | |
| 123 | + | |
| 124 | +## Stars tab | |
| 125 | + | |
| 126 | +`/{username}?tab=stars` uses the same profile shell as the GitHub stars page: | |
| 127 | + | |
| 128 | +- The left profile sidebar matches the overview profile metadata and | |
| 129 | + organization badges. | |
| 130 | +- The placeholder Lists panel is rendered so the page layout matches GitHub | |
| 131 | + while list management remains future work. | |
| 132 | +- Starred repositories are loaded in one bounded scan (`starsTabScanLimit`) and | |
| 133 | + then visibility-filtered with `policy.IsVisibleTo`. | |
| 134 | +- Both user-owned and organization-owned repository stars render from the | |
| 135 | + stored owner slug, so org-owned stars do not require an extra owner lookup. | |
| 136 | +- Filters are applied server-side for search text, repository type, language, | |
| 137 | + and sort order (`recently-starred`, `recently-active`, `stars`). | |
| 138 | + | |
| 109 | 139 | ## Self-view enrichment |
| 110 | 140 | |
| 111 | 141 | When the viewer's session matches the profile's user (`viewer.ID == user.ID`): |
internal/web/static/css/shithub.cssmodified@@ -1627,12 +1627,15 @@ button.shithub-contrib-setting-item:hover { | ||
| 1627 | 1627 | .shithub-profile-activity h2 { |
| 1628 | 1628 | margin-bottom: 1.5rem; |
| 1629 | 1629 | } |
| 1630 | +.shithub-profile-activity-timeline { | |
| 1631 | + display: grid; | |
| 1632 | + gap: 1.5rem; | |
| 1633 | +} | |
| 1630 | 1634 | .shithub-profile-activity-row { |
| 1631 | 1635 | display: grid; |
| 1632 | 1636 | grid-template-columns: 96px minmax(0, 1fr); |
| 1633 | 1637 | gap: 1.5rem; |
| 1634 | 1638 | align-items: start; |
| 1635 | - margin-bottom: 1.5rem; | |
| 1636 | 1639 | } |
| 1637 | 1640 | .shithub-profile-activity-month { |
| 1638 | 1641 | color: var(--fg-muted); |
@@ -1640,10 +1643,15 @@ button.shithub-contrib-setting-item:hover { | ||
| 1640 | 1643 | font-size: 0.875rem; |
| 1641 | 1644 | padding-top: 0.15rem; |
| 1642 | 1645 | } |
| 1646 | +.shithub-profile-activity-list { | |
| 1647 | + display: grid; | |
| 1648 | + gap: 1.25rem; | |
| 1649 | + min-width: 0; | |
| 1650 | +} | |
| 1643 | 1651 | .shithub-profile-activity-item { |
| 1644 | 1652 | position: relative; |
| 1645 | 1653 | display: flex; |
| 1646 | - align-items: center; | |
| 1654 | + align-items: flex-start; | |
| 1647 | 1655 | gap: 0.75rem; |
| 1648 | 1656 | min-height: 2.25rem; |
| 1649 | 1657 | color: var(--fg-default); |
@@ -1671,6 +1679,201 @@ button.shithub-contrib-setting-item:hover { | ||
| 1671 | 1679 | color: var(--fg-muted); |
| 1672 | 1680 | flex: 0 0 auto; |
| 1673 | 1681 | } |
| 1682 | +.shithub-profile-activity-body { | |
| 1683 | + min-width: 0; | |
| 1684 | + padding-top: 0.35rem; | |
| 1685 | +} | |
| 1686 | +.shithub-profile-activity-body strong { | |
| 1687 | + display: block; | |
| 1688 | + font-weight: 600; | |
| 1689 | +} | |
| 1690 | +.shithub-profile-activity-repos { | |
| 1691 | + list-style: none; | |
| 1692 | + margin: 0.5rem 0 0; | |
| 1693 | + padding: 0; | |
| 1694 | + display: grid; | |
| 1695 | + gap: 0.2rem; | |
| 1696 | + color: var(--fg-muted); | |
| 1697 | + font-size: 0.875rem; | |
| 1698 | +} | |
| 1699 | +.shithub-profile-activity-repos li { | |
| 1700 | + display: flex; | |
| 1701 | + flex-wrap: wrap; | |
| 1702 | + align-items: center; | |
| 1703 | + gap: 0.45rem; | |
| 1704 | + min-width: 0; | |
| 1705 | +} | |
| 1706 | +.shithub-profile-activity-repos a { | |
| 1707 | + color: var(--fg-muted); | |
| 1708 | + text-decoration: none; | |
| 1709 | +} | |
| 1710 | +.shithub-profile-activity-repos a:hover { | |
| 1711 | + color: var(--accent-fg); | |
| 1712 | + text-decoration: underline; | |
| 1713 | +} | |
| 1714 | +.shithub-profile-activity-lang { | |
| 1715 | + display: inline-flex; | |
| 1716 | + align-items: center; | |
| 1717 | + gap: 0.25rem; | |
| 1718 | +} | |
| 1719 | +.shithub-profile-activity-state { | |
| 1720 | + display: inline-flex; | |
| 1721 | + align-items: center; | |
| 1722 | + gap: 0.25rem; | |
| 1723 | +} | |
| 1724 | +.shithub-profile-activity-state b { | |
| 1725 | + display: inline-flex; | |
| 1726 | + align-items: center; | |
| 1727 | + justify-content: center; | |
| 1728 | + min-width: 1.25rem; | |
| 1729 | + height: 1.25rem; | |
| 1730 | + padding: 0 0.35rem; | |
| 1731 | + border-radius: 999px; | |
| 1732 | + color: #fff; | |
| 1733 | + background: var(--fg-muted); | |
| 1734 | + font-size: 0.75rem; | |
| 1735 | + font-weight: 600; | |
| 1736 | +} | |
| 1737 | +.shithub-profile-activity-state.is-open b { | |
| 1738 | + background: #2da44e; | |
| 1739 | +} | |
| 1740 | +.shithub-profile-activity-state.is-merged b { | |
| 1741 | + background: #8250df; | |
| 1742 | +} | |
| 1743 | +.shithub-profile-activity-state.is-closed b { | |
| 1744 | + background: #cf222e; | |
| 1745 | +} | |
| 1746 | +.shithub-profile-stars-page .shithub-user-profile-container { | |
| 1747 | + align-items: start; | |
| 1748 | +} | |
| 1749 | +.shithub-stars-main { | |
| 1750 | + display: grid; | |
| 1751 | + gap: 2rem; | |
| 1752 | +} | |
| 1753 | +.shithub-stars-section-head { | |
| 1754 | + display: flex; | |
| 1755 | + align-items: center; | |
| 1756 | + justify-content: space-between; | |
| 1757 | + gap: 1rem; | |
| 1758 | + margin-bottom: 1rem; | |
| 1759 | +} | |
| 1760 | +.shithub-stars-section-head h2, | |
| 1761 | +.shithub-stars-results h2 { | |
| 1762 | + margin: 0; | |
| 1763 | + font-size: 1rem; | |
| 1764 | + font-weight: 400; | |
| 1765 | +} | |
| 1766 | +.shithub-stars-section-head h2 span { | |
| 1767 | + color: var(--fg-muted); | |
| 1768 | +} | |
| 1769 | +.shithub-stars-list-actions { | |
| 1770 | + display: flex; | |
| 1771 | + gap: 0.5rem; | |
| 1772 | +} | |
| 1773 | +.shithub-stars-empty-list { | |
| 1774 | + min-height: 148px; | |
| 1775 | + border: 1px solid var(--border-default); | |
| 1776 | + border-radius: 6px; | |
| 1777 | + display: grid; | |
| 1778 | + place-items: center; | |
| 1779 | + align-content: center; | |
| 1780 | + gap: 0.55rem; | |
| 1781 | + padding: 1.5rem; | |
| 1782 | + text-align: center; | |
| 1783 | + color: var(--fg-default); | |
| 1784 | +} | |
| 1785 | +.shithub-stars-empty-list > span { | |
| 1786 | + color: var(--fg-muted); | |
| 1787 | +} | |
| 1788 | +.shithub-stars-empty-list p { | |
| 1789 | + margin: 0; | |
| 1790 | + color: var(--fg-muted); | |
| 1791 | + font-size: 0.875rem; | |
| 1792 | +} | |
| 1793 | +.shithub-stars-results { | |
| 1794 | + min-width: 0; | |
| 1795 | +} | |
| 1796 | +.shithub-stars-toolbar { | |
| 1797 | + display: flex; | |
| 1798 | + align-items: center; | |
| 1799 | + gap: 0.5rem; | |
| 1800 | + margin: 1rem 0; | |
| 1801 | +} | |
| 1802 | +.shithub-stars-search { | |
| 1803 | + position: relative; | |
| 1804 | + flex: 1 1 240px; | |
| 1805 | + min-width: 180px; | |
| 1806 | +} | |
| 1807 | +.shithub-stars-search svg { | |
| 1808 | + position: absolute; | |
| 1809 | + left: 0.65rem; | |
| 1810 | + top: 50%; | |
| 1811 | + transform: translateY(-50%); | |
| 1812 | + color: var(--fg-muted); | |
| 1813 | + pointer-events: none; | |
| 1814 | +} | |
| 1815 | +.shithub-stars-search input { | |
| 1816 | + width: 100%; | |
| 1817 | + padding-left: 2rem; | |
| 1818 | +} | |
| 1819 | +.shithub-stars-toolbar select { | |
| 1820 | + min-height: 32px; | |
| 1821 | + padding: 0 1.75rem 0 0.75rem; | |
| 1822 | + border: 1px solid var(--border-default); | |
| 1823 | + border-radius: 6px; | |
| 1824 | + background: var(--canvas-subtle); | |
| 1825 | + color: var(--fg-default); | |
| 1826 | + font: inherit; | |
| 1827 | +} | |
| 1828 | +.shithub-stars-list { | |
| 1829 | + list-style: none; | |
| 1830 | + margin: 0; | |
| 1831 | + padding: 0; | |
| 1832 | + border-top: 1px solid var(--border-default); | |
| 1833 | +} | |
| 1834 | +.shithub-stars-row { | |
| 1835 | + display: grid; | |
| 1836 | + grid-template-columns: minmax(0, 1fr) auto; | |
| 1837 | + gap: 1rem; | |
| 1838 | + align-items: start; | |
| 1839 | + padding: 1.25rem 0; | |
| 1840 | + border-bottom: 1px solid var(--border-default); | |
| 1841 | +} | |
| 1842 | +.shithub-stars-row h3 { | |
| 1843 | + margin: 0; | |
| 1844 | + font-size: 1.125rem; | |
| 1845 | + font-weight: 600; | |
| 1846 | +} | |
| 1847 | +.shithub-stars-row h3 a { | |
| 1848 | + color: var(--accent-fg); | |
| 1849 | + text-decoration: none; | |
| 1850 | +} | |
| 1851 | +.shithub-stars-row h3 a:hover { | |
| 1852 | + text-decoration: underline; | |
| 1853 | +} | |
| 1854 | +.shithub-stars-row p { | |
| 1855 | + margin: 0.45rem 0 0; | |
| 1856 | + color: var(--fg-muted); | |
| 1857 | +} | |
| 1858 | +.shithub-stars-meta { | |
| 1859 | + list-style: none; | |
| 1860 | + margin: 0.65rem 0 0; | |
| 1861 | + padding: 0; | |
| 1862 | + display: flex; | |
| 1863 | + flex-wrap: wrap; | |
| 1864 | + align-items: center; | |
| 1865 | + gap: 0.75rem; | |
| 1866 | + color: var(--fg-muted); | |
| 1867 | + font-size: 0.875rem; | |
| 1868 | +} | |
| 1869 | +.shithub-stars-meta li { | |
| 1870 | + display: inline-flex; | |
| 1871 | + align-items: center; | |
| 1872 | + gap: 0.25rem; | |
| 1873 | +} | |
| 1874 | +.shithub-stars-starred svg:first-child { | |
| 1875 | + color: #d29922; | |
| 1876 | +} | |
| 1674 | 1877 | @media (max-width: 980px) { |
| 1675 | 1878 | .shithub-profile-tabs-shell .shithub-profile-tabs { |
| 1676 | 1879 | padding: 0 1rem; |
@@ -1754,6 +1957,19 @@ button.shithub-contrib-setting-item:hover { | ||
| 1754 | 1957 | .shithub-profile-activity-item::before { |
| 1755 | 1958 | display: none; |
| 1756 | 1959 | } |
| 1960 | + .shithub-stars-toolbar, | |
| 1961 | + .shithub-stars-row, | |
| 1962 | + .shithub-stars-section-head { | |
| 1963 | + align-items: stretch; | |
| 1964 | + flex-direction: column; | |
| 1965 | + display: flex; | |
| 1966 | + } | |
| 1967 | + .shithub-stars-list-actions { | |
| 1968 | + width: 100%; | |
| 1969 | + } | |
| 1970 | + .shithub-stars-list-actions .shithub-button { | |
| 1971 | + flex: 1; | |
| 1972 | + } | |
| 1757 | 1973 | } |
| 1758 | 1974 | |
| 1759 | 1975 | /* ----- settings shell (S10) ----- */ |
internal/web/templates/_layout.htmlmodified@@ -331,6 +331,20 @@ | ||
| 331 | 331 | refreshPins(); |
| 332 | 332 | })(); |
| 333 | 333 | |
| 334 | + (function () { | |
| 335 | + document.querySelectorAll("[data-profile-activity]").forEach(function (root) { | |
| 336 | + var button = root.querySelector("[data-profile-activity-show-more]"); | |
| 337 | + if (!button) return; | |
| 338 | + button.addEventListener("click", function () { | |
| 339 | + root.querySelectorAll("[data-profile-activity-more]").forEach(function (row) { | |
| 340 | + row.hidden = false; | |
| 341 | + row.removeAttribute("data-profile-activity-more"); | |
| 342 | + }); | |
| 343 | + button.hidden = true; | |
| 344 | + }); | |
| 345 | + }); | |
| 346 | + })(); | |
| 347 | + | |
| 334 | 348 | (function () { |
| 335 | 349 | var copyIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>'; |
| 336 | 350 | var checkIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path></svg>'; |
internal/web/templates/profile/stars_tab.htmlmodified@@ -1,39 +1,136 @@ | ||
| 1 | 1 | {{ define "page" -}} |
| 2 | -<section class="shithub-profile"> | |
| 3 | - <header class="shithub-profile-header"> | |
| 4 | - <img class="shithub-profile-avatar" src="{{ .AvatarURL }}" alt="" width="120" height="120"> | |
| 5 | - <div class="shithub-profile-id"> | |
| 6 | - <h1 class="shithub-profile-name"> | |
| 7 | - {{ if .User.DisplayName }}{{ .User.DisplayName }}{{ else }}{{ .User.Username }}{{ end }} | |
| 8 | - </h1> | |
| 9 | - <p class="shithub-profile-handle">@{{ .User.Username }}</p> | |
| 10 | - </div> | |
| 11 | - </header> | |
| 12 | - | |
| 13 | - {{ template "profile-tabs" . }} | |
| 14 | - | |
| 15 | - {{ if .Stars }} | |
| 16 | - <ul class="shithub-social-list"> | |
| 17 | - {{ range .Stars }} | |
| 18 | - <li> | |
| 19 | - <a href="/{{ .OwnerName }}/{{ .RepoName }}"><strong>{{ .OwnerName }}/{{ .RepoName }}</strong></a> | |
| 20 | - {{ if eq .Visibility "private" }}<span class="shithub-pill shithub-pill-private">private</span>{{ end }} | |
| 21 | - {{ if .PrimaryLanguage }}<small>{{ .PrimaryLanguage }}</small>{{ end }} | |
| 22 | - <small>★ {{ .StarCount }}</small> | |
| 23 | - <small><time datetime="{{ .StarredAt.Format "2006-01-02T15:04:05Z" }}">starred {{ relativeTime .StarredAt }}</time></small> | |
| 24 | - {{ if .Description }}<p class="shithub-meta">{{ .Description }}</p>{{ end }} | |
| 25 | - </li> | |
| 26 | - {{ end }} | |
| 27 | - </ul> | |
| 28 | - {{ else }} | |
| 29 | - <p class="shithub-empty">No starred repositories visible.</p> | |
| 30 | - {{ end }} | |
| 31 | - | |
| 32 | - {{ if or .HasPrev .HasNext }} | |
| 33 | - <nav class="shithub-pagination"> | |
| 34 | - {{ if .HasPrev }}<a href="?tab=stars&page={{ sub .Page 1 }}" class="shithub-button">Previous</a>{{ end }} | |
| 35 | - {{ if .HasNext }}<a href="?tab=stars&page={{ add .Page 1 }}" class="shithub-button">Next</a>{{ end }} | |
| 36 | - </nav> | |
| 37 | - {{ end }} | |
| 2 | +<section class="shithub-user-profile shithub-profile-stars-page"> | |
| 3 | + <div class="shithub-profile-tabs-shell"> | |
| 4 | + {{ template "profile-tabs" . }} | |
| 5 | + </div> | |
| 6 | + | |
| 7 | + <div class="shithub-user-profile-container"> | |
| 8 | + <aside class="shithub-user-profile-sidebar" aria-label="{{ .User.Username }} profile"> | |
| 9 | + <a class="shithub-profile-avatar-link" href="{{ .AvatarURL }}"> | |
| 10 | + <img class="shithub-profile-avatar" src="{{ .AvatarURL }}" alt="@{{ .User.Username }}" width="296" height="296"> | |
| 11 | + </a> | |
| 12 | + <div class="shithub-profile-names"> | |
| 13 | + <h1> | |
| 14 | + <span class="shithub-profile-name">{{ .DisplayName }}</span> | |
| 15 | + <span class="shithub-profile-handle">{{ .User.Username }}</span> | |
| 16 | + </h1> | |
| 17 | + {{ if .User.Pronouns }}<span class="shithub-profile-pronouns">{{ .User.Pronouns }}</span>{{ end }} | |
| 18 | + </div> | |
| 19 | + | |
| 20 | + {{ if .User.Bio }}<div class="shithub-profile-bio">{{ .User.Bio }}</div>{{ end }} | |
| 21 | + {{ if .IsSelf }}<a href="/settings/profile" class="shithub-button shithub-button-block">Edit profile</a>{{ end }} | |
| 22 | + | |
| 23 | + <p class="shithub-profile-follow-counts"> | |
| 24 | + {{ octicon "people" }} | |
| 25 | + <a href="/{{ .User.Username }}?tab=followers"><strong>{{ .FollowersCount }}</strong> followers</a> | |
| 26 | + <span class="shithub-profile-dot" aria-hidden="true">·</span> | |
| 27 | + <a href="/{{ .User.Username }}?tab=following"><strong>{{ .FollowingCount }}</strong> following</a> | |
| 28 | + </p> | |
| 29 | + | |
| 30 | + <ul class="shithub-profile-vcard"> | |
| 31 | + {{ if .User.Company }}<li>{{ octicon "organization" }} <span>{{ .User.Company }}</span></li>{{ end }} | |
| 32 | + {{ if .User.Location }}<li>{{ octicon "location" }} <span>{{ .User.Location }}</span></li>{{ end }} | |
| 33 | + {{ if .WebsiteSafe }}<li>{{ octicon "link" }} <a href="{{ .WebsiteSafe }}" rel="nofollow noopener">{{ .User.Website }}</a></li>{{ end }} | |
| 34 | + <li>{{ octicon "calendar" }} <span>Joined {{ .JoinedFormatted }}</span></li> | |
| 35 | + </ul> | |
| 36 | + | |
| 37 | + {{ if .Orgs }} | |
| 38 | + <section class="shithub-profile-sidebar-section" aria-labelledby="stars-profile-orgs-heading"> | |
| 39 | + <h2 id="stars-profile-orgs-heading">Organizations</h2> | |
| 40 | + <div class="shithub-profile-orgs"> | |
| 41 | + {{ range .Orgs }} | |
| 42 | + <a href="/{{ .Slug }}" aria-label="{{ .DisplayName }}"> | |
| 43 | + <img src="{{ .AvatarURL }}" alt="" width="32" height="32"> | |
| 44 | + </a> | |
| 45 | + {{ end }} | |
| 46 | + </div> | |
| 47 | + </section> | |
| 48 | + {{ end }} | |
| 49 | + </aside> | |
| 50 | + | |
| 51 | + <main class="shithub-user-profile-main shithub-stars-main"> | |
| 52 | + <section class="shithub-stars-lists" aria-labelledby="stars-lists-heading"> | |
| 53 | + <div class="shithub-stars-section-head"> | |
| 54 | + <h2 id="stars-lists-heading">Lists <span>(0)</span></h2> | |
| 55 | + <div class="shithub-stars-list-actions"> | |
| 56 | + <button type="button" class="shithub-button" disabled>Sort {{ octicon "triangle-down" }}</button> | |
| 57 | + <button type="button" class="shithub-button shithub-button-primary" disabled>Create list</button> | |
| 58 | + </div> | |
| 59 | + </div> | |
| 60 | + <div class="shithub-stars-empty-list"> | |
| 61 | + <span>{{ octicon "star" }}</span> | |
| 62 | + <strong>Create your first list</strong> | |
| 63 | + <p>Lists make it easier to organize and curate repositories that you have starred. <a href="/{{ .User.Username }}?tab=stars">Create your first list.</a></p> | |
| 64 | + </div> | |
| 65 | + </section> | |
| 66 | + | |
| 67 | + <section class="shithub-stars-results" aria-labelledby="stars-heading"> | |
| 68 | + <h2 id="stars-heading">Stars</h2> | |
| 69 | + <form class="shithub-stars-toolbar" method="get" action="/{{ .User.Username }}" aria-label="{{ .StarsSearchLabel }}"> | |
| 70 | + <input type="hidden" name="tab" value="stars"> | |
| 71 | + <label class="shithub-stars-search"> | |
| 72 | + <span class="sr-only">Search stars</span> | |
| 73 | + {{ octicon "search" }} | |
| 74 | + <input type="search" name="q" value="{{ .StarFilters.Query }}" placeholder="Search stars" autocomplete="off"> | |
| 75 | + </label> | |
| 76 | + <button type="submit" class="shithub-button">Search</button> | |
| 77 | + <label> | |
| 78 | + <span class="sr-only">Repository type</span> | |
| 79 | + <select name="type" onchange="this.form.submit()"> | |
| 80 | + <option value="all"{{ if eq .StarFilters.Type "all" }} selected{{ end }}>Type: All</option> | |
| 81 | + <option value="public"{{ if eq .StarFilters.Type "public" }} selected{{ end }}>Public</option> | |
| 82 | + <option value="private"{{ if eq .StarFilters.Type "private" }} selected{{ end }}>Private</option> | |
| 83 | + </select> | |
| 84 | + </label> | |
| 85 | + <label> | |
| 86 | + <span class="sr-only">Language</span> | |
| 87 | + <select name="language" onchange="this.form.submit()"> | |
| 88 | + <option value=""{{ if not .StarFilters.Language }} selected{{ end }}>Language</option> | |
| 89 | + {{ range .LanguageOptions }}<option value="{{ . }}"{{ if eq $.StarFilters.Language . }} selected{{ end }}>{{ . }}</option>{{ end }} | |
| 90 | + </select> | |
| 91 | + </label> | |
| 92 | + <label> | |
| 93 | + <span class="sr-only">Sort</span> | |
| 94 | + <select name="sort" onchange="this.form.submit()"> | |
| 95 | + <option value="recently-starred"{{ if eq .StarFilters.Sort "recently-starred" }} selected{{ end }}>Sort by: Recently starred</option> | |
| 96 | + <option value="recently-active"{{ if eq .StarFilters.Sort "recently-active" }} selected{{ end }}>Recently active</option> | |
| 97 | + <option value="stars"{{ if eq .StarFilters.Sort "stars" }} selected{{ end }}>Most stars</option> | |
| 98 | + </select> | |
| 99 | + </label> | |
| 100 | + </form> | |
| 101 | + | |
| 102 | + {{ if .Stars }} | |
| 103 | + <ol class="shithub-stars-list"> | |
| 104 | + {{ range .Stars }} | |
| 105 | + <li class="shithub-stars-row"> | |
| 106 | + <div class="shithub-stars-row-main"> | |
| 107 | + <h3> | |
| 108 | + <a href="{{ .URL }}">{{ .FullName }}</a> | |
| 109 | + {{ if .IsPrivate }}<span class="shithub-pill shithub-pill-private">Private</span>{{ end }} | |
| 110 | + </h3> | |
| 111 | + {{ if .Description }}<p>{{ .Description }}</p>{{ end }} | |
| 112 | + <ul class="shithub-stars-meta"> | |
| 113 | + {{ if .PrimaryLanguage }}<li><span class="shithub-language-dot" style="background-color: {{ .LanguageColor }};"></span>{{ .PrimaryLanguage }}</li>{{ end }} | |
| 114 | + <li>{{ octicon "star" }} {{ .StarCount }}</li> | |
| 115 | + <li>Updated <time datetime="{{ .UpdatedAt.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .UpdatedAt }}</time></li> | |
| 116 | + </ul> | |
| 117 | + </div> | |
| 118 | + <button type="button" class="shithub-button shithub-stars-starred" disabled>{{ octicon "star" }} Starred {{ octicon "triangle-down" }}</button> | |
| 119 | + </li> | |
| 120 | + {{ end }} | |
| 121 | + </ol> | |
| 122 | + {{ else }} | |
| 123 | + <p class="shithub-empty">No starred repositories visible.</p> | |
| 124 | + {{ end }} | |
| 125 | + | |
| 126 | + {{ if or .HasPrev .HasNext }} | |
| 127 | + <nav class="shithub-pagination"> | |
| 128 | + {{ if .HasPrev }}<a href="{{ .PrevHref }}" class="shithub-button">Previous</a>{{ end }} | |
| 129 | + {{ if .HasNext }}<a href="{{ .NextHref }}" class="shithub-button">Next</a>{{ end }} | |
| 130 | + </nav> | |
| 131 | + {{ end }} | |
| 132 | + </section> | |
| 133 | + </main> | |
| 134 | + </div> | |
| 38 | 135 | </section> |
| 39 | 136 | {{- end }} |
internal/web/templates/profile/view.htmlmodified@@ -175,20 +175,51 @@ | ||
| 175 | 175 | </div> |
| 176 | 176 | </section> |
| 177 | 177 | |
| 178 | - <section class="shithub-profile-activity" aria-labelledby="activity-h"> | |
| 178 | + <section class="shithub-profile-activity" aria-labelledby="activity-h" data-profile-activity> | |
| 179 | 179 | <h2 id="activity-h">Contribution activity</h2> |
| 180 | + {{ if .Contributions.Activity }} | |
| 181 | + <div class="shithub-profile-activity-timeline"> | |
| 182 | + {{ range .Contributions.Activity }} | |
| 183 | + <div class="shithub-profile-activity-row"{{ if .InitiallyHidden }} hidden data-profile-activity-more{{ end }}> | |
| 184 | + <div class="shithub-profile-activity-month">{{ .Label }}</div> | |
| 185 | + <div class="shithub-profile-activity-list"> | |
| 186 | + {{ range .Items }} | |
| 187 | + <article class="shithub-profile-activity-item shithub-profile-activity-item-{{ .Kind }}"> | |
| 188 | + <span class="shithub-profile-activity-icon">{{ octicon .Icon }}</span> | |
| 189 | + <div class="shithub-profile-activity-body"> | |
| 190 | + <strong>{{ .Summary }}</strong> | |
| 191 | + {{ if .Repos }} | |
| 192 | + <ol class="shithub-profile-activity-repos"> | |
| 193 | + {{ range .Repos }} | |
| 194 | + <li> | |
| 195 | + {{ if .URL }}<a href="{{ .URL }}">{{ .FullName }}</a>{{ else }}<span>{{ .FullName }}</span>{{ end }} | |
| 196 | + {{ if .Language }}<span class="shithub-profile-activity-lang"><span class="shithub-language-dot" style="background-color: {{ .LanguageColor }};"></span>{{ .Language }}</span>{{ end }} | |
| 197 | + {{ if .CountLabel }}<span>{{ .CountLabel }}</span>{{ end }} | |
| 198 | + {{ range .StateCounts }}<span class="shithub-profile-activity-state is-{{ .Class }}"><b>{{ .Count }}</b> {{ .Label }}</span>{{ end }} | |
| 199 | + {{ if .DateLabel }}<time>{{ .DateLabel }}</time>{{ end }} | |
| 200 | + </li> | |
| 201 | + {{ end }} | |
| 202 | + </ol> | |
| 203 | + {{ end }} | |
| 204 | + </div> | |
| 205 | + </article> | |
| 206 | + {{ end }} | |
| 207 | + </div> | |
| 208 | + </div> | |
| 209 | + {{ end }} | |
| 210 | + </div> | |
| 211 | + {{ if .Contributions.HasMoreActivity }}<button type="button" class="shithub-button shithub-button-block" data-profile-activity-show-more>Show more activity</button>{{ end }} | |
| 212 | + {{ else }} | |
| 180 | 213 | <div class="shithub-profile-activity-row"> |
| 181 | 214 | <div class="shithub-profile-activity-month">{{ .Contributions.MonthLabel }}</div> |
| 182 | - <div class="shithub-profile-activity-item"> | |
| 183 | - <span class="shithub-profile-activity-icon">{{ octicon "repo" }}</span> | |
| 184 | - {{ if .Contributions.MonthCommitCount }} | |
| 185 | - <strong>Created {{ .Contributions.MonthCommitCount }} commit{{ pluralize .Contributions.MonthCommitCount "" "s" }} in {{ .Contributions.MonthRepoCount }} repositor{{ pluralize .Contributions.MonthRepoCount "y" "ies" }}</strong> | |
| 186 | - {{ else }} | |
| 187 | - <strong>No activity in {{ .Contributions.MonthLabel }}</strong> | |
| 188 | - {{ end }} | |
| 215 | + <div class="shithub-profile-activity-list"> | |
| 216 | + <article class="shithub-profile-activity-item"> | |
| 217 | + <span class="shithub-profile-activity-icon">{{ octicon "repo" }}</span> | |
| 218 | + <div class="shithub-profile-activity-body"><strong>No activity in {{ .Contributions.MonthLabel }}</strong></div> | |
| 219 | + </article> | |
| 189 | 220 | </div> |
| 190 | 221 | </div> |
| 191 | - <button type="button" class="shithub-button shithub-button-block" disabled>Show more activity</button> | |
| 222 | + {{ end }} | |
| 192 | 223 | </section> |
| 193 | 224 | </main> |
| 194 | 225 | </div> |