mirror of
https://github.com/caddyserver/website.git
synced 2025-04-29 08:19:14 -04:00
feat(redesign): Download page
This commit is contained in:
parent
7294fc7309
commit
982393ff91
4 changed files with 415 additions and 8 deletions
189
new/resources/css/download.css
Normal file
189
new/resources/css/download.css
Normal file
|
@ -0,0 +1,189 @@
|
|||
.card {
|
||||
border: 1px solid rgba(226, 232, 240, 0.8);
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--body-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06);
|
||||
}
|
||||
|
||||
.wrapper.list {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#side-panel-packages {
|
||||
padding-top: 32px;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
#side-panel-packages>div {
|
||||
padding: 1rem 1rem 1rem 0;
|
||||
overflow-y: scroll;
|
||||
width: 300px;
|
||||
max-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#packages {
|
||||
width: 100%;
|
||||
padding-top: 32px;
|
||||
padding-bottom: 32px;
|
||||
display: grid;
|
||||
gap: 48px;
|
||||
}
|
||||
|
||||
#packages>section>h2 {
|
||||
padding-bottom: 16px;
|
||||
color: rgb(14, 110, 189);
|
||||
border-color: rgb(14, 110, 189);
|
||||
}
|
||||
|
||||
.card-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding-left: 16px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-title-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: lighter;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.card-title-info {
|
||||
display: inline-flex;
|
||||
gap: 16px;
|
||||
font-size: 90%;
|
||||
color: var(--text-color-muted);
|
||||
}
|
||||
|
||||
.card-title-info>span>svg {
|
||||
margin-right: -4px;
|
||||
}
|
||||
|
||||
.card-header>:first-child>span:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.card-description {
|
||||
display: flex;
|
||||
color: var(--text-color-muted);
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.card-description>p {
|
||||
font-weight: 400;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 4;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.card-button {
|
||||
margin: 0 auto;
|
||||
min-width: fit-content;
|
||||
white-space: nowrap;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.filters {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 2fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
.card-description {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.filters {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
padding: 0.5rem;
|
||||
height: 3rem;
|
||||
font-size: 100%;
|
||||
font-weight: 600;
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
border-radius: 0.5rem;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.filters>div {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
select {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding-left: 1rem;
|
||||
padding-right: 2.5rem;
|
||||
font-size: .875rem;
|
||||
line-height: 1.25rem;
|
||||
line-height: 2;
|
||||
min-height: 3rem;
|
||||
border-width: 1px;
|
||||
border-color: var(--text-color-muted);
|
||||
background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
|
||||
background-position: calc(100% - 20px) calc(1px + 50%), calc(100% - 16.1px) calc(1px + 50%);
|
||||
background-size: 4px 4px, 4px 4px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
120
new/resources/js/download.js
Normal file
120
new/resources/js/download.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
class Package {
|
||||
/**
|
||||
* @typedef {Object} Module
|
||||
* @property {string} docs
|
||||
* @property {string} name
|
||||
* @property {string} package
|
||||
* @property {string} repo
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Pkg
|
||||
* @property {string} id
|
||||
* @property {string} path
|
||||
* @property {string} published
|
||||
* @property {boolean} listed
|
||||
* @property {boolean} available
|
||||
* @property {number} downloads
|
||||
* @property {ReadonlyArray<Module>} modules
|
||||
* @property {string} repo
|
||||
* @property {string} name
|
||||
*/
|
||||
|
||||
/** @type {string} */
|
||||
pkgURL = "https://localhost/api/packages";
|
||||
|
||||
/**
|
||||
* @type {ReadonlyArray<Pkg>}
|
||||
*/
|
||||
packages = [];
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
filter = '';
|
||||
|
||||
/**
|
||||
* @returns Promise<>
|
||||
*/
|
||||
getPackages() {
|
||||
return fetch(this.pkgURL, { headers: { 'X-Requested-With': 'XMLHttpRequest', Origin: 'https://caddyserver.com' } })
|
||||
.then(res => res.json())
|
||||
.then(({ result }) => this.packages = result.sort((a, b) => a.downloads - b.downloads).map(item => ({ ...item, description: item.modules?.map(m => m.docs ?? m.name).join('\n') ?? '', name: item.repo.split('/')[4].toLowerCase() })));
|
||||
}
|
||||
|
||||
setFilterValue(value) {
|
||||
this.filter = value;
|
||||
}
|
||||
|
||||
getSearchPackages(pkgs) {
|
||||
if (!this.filter) {
|
||||
return pkgs;
|
||||
}
|
||||
|
||||
return pkgs.filter(pkg => pkg.name.includes(this.filter) || pkg.repo.includes(this.filter) || pkg.description.includes(this.filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {'alphabetically' | 'type' | 'download'} groupBy
|
||||
* @return {
|
||||
* Record<string, Pkg> | ReadonlyArray<Pkg}
|
||||
*/
|
||||
group(groupBy = 'alphabetically') {
|
||||
const pkgs = this.getSearchPackages(this.packages);
|
||||
switch (groupBy) {
|
||||
case 'alphabetically':
|
||||
return pkgs.sort((a,b) => a.name.localeCompare(b.name));
|
||||
case 'download':
|
||||
return pkgs.sort((a,b) => b.downloads - a.downloads);
|
||||
case 'type':
|
||||
return pkgs.reduce((acc, current) => {
|
||||
if (!current?.modules?.length) {
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
current.modules.forEach(module => {
|
||||
let moduleName = module.name
|
||||
if (module.name.includes('.')) {
|
||||
const splitted = module.name.split('.')
|
||||
moduleName = `${splitted[0]}.${splitted[1]}`
|
||||
}
|
||||
if (acc[moduleName]) {
|
||||
acc[moduleName] = [...acc[moduleName], current];
|
||||
}
|
||||
})
|
||||
|
||||
return acc;
|
||||
}, {
|
||||
"http.handlers": [],
|
||||
"http.matchers": [],
|
||||
"dns.providers": [],
|
||||
"http.encoders": [],
|
||||
"caddy.config_loaders": [],
|
||||
"caddy.fs": [],
|
||||
"caddy.listeners": [],
|
||||
"caddy.logging.encoders": [],
|
||||
"caddy.logging.encoders.filter": [],
|
||||
"caddy.logging.writers": [],
|
||||
"caddy.storage": [],
|
||||
"events.handlers": [],
|
||||
"http.authentication.hashes": [],
|
||||
"http.authentication.providers": [],
|
||||
"http.ip_sources": [],
|
||||
"http.precompressed": [],
|
||||
"http.reverse_proxy.circuit_breakers": [],
|
||||
"http.reverse_proxy.selection_policies": [],
|
||||
"http.reverse_proxy.transport": [],
|
||||
"http.reverse_proxy.upstreams": [],
|
||||
"tls.certificates": [],
|
||||
"tls.client_auth": [],
|
||||
"tls.handshake_match": [],
|
||||
"tls.issuance": [],
|
||||
"tls.get_certificate": [],
|
||||
"tls.stek": [],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const packageManager = new Package();
|
Loading…
Add table
Add a link
Reference in a new issue