Skip to content

Commit 992beb3

Browse files
authored
Merge pull request #51 from DefGuard/server-download
Server download
2 parents 5a3419b + 43c818d commit 992beb3

File tree

5 files changed

+319
-73
lines changed

5 files changed

+319
-73
lines changed
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
---
2+
import { DownloadIcon } from "../base/icons/DownloadIcon";
3+
import { CheckIcon } from "../base/icons/CheckIcon";
4+
import { PlatformType } from "../base/types/platform";
5+
6+
interface Props {
7+
repoUrl: string;
8+
}
9+
10+
const { repoUrl } = Astro.props;
11+
12+
// Extract owner and repo from the URL
13+
const urlParts = repoUrl.split('/');
14+
const owner = urlParts[urlParts.length - 2];
15+
const repo = urlParts[urlParts.length - 1];
16+
17+
// Fetch releases from GitHub API
18+
const response = await fetch(
19+
`https://api.github.com/repos/${owner}/${repo}/releases?per_page=10`
20+
);
21+
const releases = await response.json();
22+
23+
// Filter only stable releases (not pre-releases) and get the latest one
24+
const stableReleases = releases.filter((release: any) => !release.prerelease);
25+
const latestRelease = stableReleases[0]; // Get only the latest release
26+
27+
interface Asset {
28+
name: string;
29+
browser_download_url: string;
30+
size: number;
31+
}
32+
33+
function getAssetDescription(assetName: string): string {
34+
// Mapping based on provided examples
35+
if (/\.deb$/.test(assetName) && /x86_64-unknown-linux-gnu/.test(assetName)) {
36+
return "Debian / Ubuntu (x64)";
37+
}
38+
if (/\.rpm$/.test(assetName) && /x86_64-unknown-linux-gnu/.test(assetName)) {
39+
return "Red Hat / Fedora (x64)";
40+
}
41+
if (/\.pkg$/.test(assetName) && /x86_64-unknown-freebsd/.test(assetName)) {
42+
return "FreeBSD (x64, pkg)";
43+
}
44+
if (/\.tar\.gz$/.test(assetName) && /aarch64-unknown-linux-gnu/.test(assetName)) {
45+
return "Linux (ARM64, tar.gz)";
46+
}
47+
if (/\.tar\.gz$/.test(assetName) && /x86_64-unknown-freebsd/.test(assetName)) {
48+
return "FreeBSD (x64, tar.gz)";
49+
}
50+
if (/\.tar\.gz$/.test(assetName) && /x86_64-unknown-linux-gnu/.test(assetName)) {
51+
return "Linux (x64, tar.gz)";
52+
}
53+
return "";
54+
}
55+
56+
function getPlatformType(assetName: string): PlatformType {
57+
if (assetName.includes('windows')) return PlatformType.WINDOWS;
58+
if (assetName.includes('linux') && assetName.includes('.deb')) return PlatformType.DEBIAN;
59+
if (assetName.includes('macos') && (assetName.includes('aarch64') || assetName.includes('arm64'))) return PlatformType.MACOSARM;
60+
if (assetName.includes('macos') && (assetName.includes('x86_64') || assetName.includes('amd64'))) return PlatformType.MACOSINTEL;
61+
return PlatformType.DEBIAN; // Default to Debian if unknown
62+
}
63+
---
64+
65+
<div class="github-releases">
66+
{latestRelease && (
67+
<div class="release-container">
68+
<div class="release-header">
69+
<div class="release-version-info">
70+
Latest stable release: {latestRelease.tag_name.replace(/^v/, "")} | View changelog →
71+
<a href={latestRelease.html_url} target="_blank" rel="noopener noreferrer">
72+
{new Date(latestRelease.published_at).toLocaleDateString()}
73+
</a>
74+
</div>
75+
</div>
76+
{latestRelease.assets && latestRelease.assets.length > 0 && (
77+
<div class="assets-container">
78+
<ul class="assets-list">
79+
{(() => {
80+
const assets = latestRelease.assets;
81+
const tarGzIndex = assets.findIndex((a: any) => a.name.includes('.tar.gz'));
82+
return assets.map((asset: any, idx: number) => [
83+
(idx === tarGzIndex && tarGzIndex !== 0) ? (
84+
<li class="asset-separator">
85+
<div class="download-separator">
86+
<hr />
87+
<p>compressed archives</p>
88+
<hr />
89+
</div>
90+
</li>
91+
) : null,
92+
<li class="asset-item">
93+
<a
94+
href={asset.browser_download_url}
95+
target="_blank"
96+
rel="noopener noreferrer"
97+
class="download-button-wrapper"
98+
title={`Size: ${(asset.size / 1024 / 1024).toFixed(2)} MB`}
99+
>
100+
<div class="download-text-wrapper">
101+
<span class="download-filename">Download now</span>
102+
{getAssetDescription(asset.name) && <p>{getAssetDescription(asset.name)}</p>}
103+
</div>
104+
<DownloadIcon />
105+
</a>
106+
</li>
107+
]).flat();
108+
})()}
109+
</ul>
110+
<div class="release-note">
111+
For pre-release archives, visit the
112+
<a href={`https://github.com/${owner}/${repo}/releases`} target="_blank" rel="noopener noreferrer">GitHub Releases page</a>
113+
to access all assets, including source code.
114+
</div>
115+
</div>
116+
)}
117+
</div>
118+
)}
119+
</div>
120+
121+
<style lang="scss">
122+
.github-releases {
123+
padding-top: 1rem;
124+
background: var(--theme-card-bg);
125+
border-radius: 8px;
126+
}
127+
128+
h3 {
129+
margin: 0 0 1rem 0;
130+
color: var(--theme-text);
131+
font-size: 1.2rem;
132+
text-align: center;
133+
}
134+
135+
136+
.release-header {
137+
margin-bottom: 0.5rem;
138+
}
139+
140+
.release-version-info {
141+
@include typography(pricebox-list);
142+
margin-bottom: 20px;
143+
line-height: 1.2;
144+
font-size: 16px;
145+
146+
a {
147+
text-decoration: underline;
148+
color: inherit;
149+
white-space: nowrap;
150+
transition: color 0.2s;
151+
}
152+
a:hover {
153+
color: #0c8ce0;
154+
}
155+
}
156+
157+
.assets-container {
158+
margin-top: 0.5rem;
159+
padding-left: 0;
160+
}
161+
162+
.assets-list {
163+
list-style: none;
164+
padding: 0;
165+
margin: 0;
166+
display: flex;
167+
flex-direction: column;
168+
gap: 0.5rem;
169+
}
170+
171+
.asset-item {
172+
margin: 0;
173+
padding: 0;
174+
}
175+
176+
.download-button-wrapper {
177+
display: flex;
178+
height: 64px;
179+
padding: 0px 20px;
180+
justify-content: space-between;
181+
align-items: center;
182+
align-self: stretch;
183+
border: 1px solid var(--text-body-primary);
184+
text-decoration: none;
185+
color: inherit;
186+
cursor: pointer;
187+
transition: all 0.2s ease;
188+
189+
// Default state for SVG
190+
svg {
191+
path {
192+
stroke: currentColor;
193+
transition: stroke 0.2s ease;
194+
}
195+
}
196+
197+
&:hover {
198+
background-color: var(--surface-frame-bg);
199+
border-color: #0c8ce0;
200+
color: #0c8ce0; // Set color on the wrapper itself
201+
202+
.download-text-wrapper {
203+
.download-filename {
204+
color: #0c8ce0;
205+
}
206+
p {
207+
color: var(--theme-text);
208+
}
209+
}
210+
211+
svg {
212+
path {
213+
stroke: currentColor; // Use currentColor to inherit from parent
214+
}
215+
}
216+
}
217+
}
218+
219+
.download-text-wrapper {
220+
display: flex;
221+
flex-direction: column;
222+
justify-content: flex-start;
223+
align-items: flex-start;
224+
@include typography(paragraph);
225+
226+
.download-filename {
227+
@include typography(paragraph);
228+
font-size: calc(18px * var(--font-scale-factor));
229+
color: var(--theme-text);
230+
}
231+
232+
p {
233+
@include typography(footer);
234+
margin: 0;
235+
color: var(--theme-text);
236+
}
237+
}
238+
239+
.btn {
240+
all: unset;
241+
padding: 20px;
242+
svg {
243+
path,
244+
rect {
245+
fill: none;
246+
stroke: var(--text-body-primary);
247+
transition: stroke 0.2s ease;
248+
}
249+
}
250+
}
251+
252+
.download-separator {
253+
display: flex;
254+
align-items: center;
255+
gap: 40px;
256+
align-self: stretch;
257+
text-align: center;
258+
@include typography(footer);
259+
padding-top: 1.5rem;
260+
padding-bottom: 1.5rem;
261+
262+
hr {
263+
flex: 1;
264+
height: 1px;
265+
background-color: var(--border-separator);
266+
border: none;
267+
margin: 0;
268+
}
269+
270+
p {
271+
width: 30%;
272+
}
273+
}
274+
275+
@include break-down(sm) {
276+
P {
277+
font-size: 12px;
278+
font-weight: 300;
279+
}
280+
.download-separator p {
281+
width: 30%;
282+
}
283+
}
284+
285+
.release-note {
286+
margin-top: 2rem;
287+
text-align: center;
288+
@include typography(footer);
289+
color: var(--theme-text-light);
290+
a {
291+
color: #0c8ce0;
292+
text-decoration: underline;
293+
transition: color 0.2s;
294+
}
295+
a:hover {
296+
color: #005fa3;
297+
}
298+
}
299+
</style>
Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,22 @@
1-
import { useEffect, useState } from "react";
2-
31
import { PlatformType } from "../types/platform";
42

5-
interface DownloadProps {
6-
platformType: PlatformType;
7-
owner: string;
8-
repo: string;
9-
version: string;
3+
interface DownloadIconProps {
4+
width?: number;
5+
height?: number;
106
}
117

12-
export const DownloadIcon = ({ platformType, owner, repo, version }: DownloadProps) => {
13-
const [downloadName, setDownloadName] = useState("");
14-
15-
useEffect(() => {
16-
switch (platformType) {
17-
case PlatformType.WINDOWS: {
18-
setDownloadName(`defguard-client_${version}_x64_en-US.exe`);
19-
break;
20-
}
21-
case PlatformType.MACOSARM: {
22-
setDownloadName(`defguard-aarch64-apple-darwin-${version}.pkg`);
23-
break;
24-
}
25-
case PlatformType.MACOSINTEL: {
26-
setDownloadName(`defguard-x86_64-apple-darwin-${version}.pkg`);
27-
break;
28-
}
29-
case PlatformType.DEBIAN: {
30-
setDownloadName(`defguard-client_${version}_amd64.deb`);
31-
break;
32-
}
33-
case PlatformType.ARCHLINUX: {
34-
setDownloadName(`defguard-client_${version}_amd64.deb`);
35-
break;
36-
}
37-
}
38-
}, [platformType, version]);
39-
8+
export const DownloadIcon = ({ width = 16, height = 16 }: DownloadIconProps) => {
409
return (
41-
<a
42-
href={`https://github.com/${owner}/${repo}/releases/download/v${version}/${downloadName}`}
43-
aria-label="download-icon"
10+
<svg
11+
xmlns="http://www.w3.org/2000/svg"
12+
width={width}
13+
height={height}
14+
viewBox="0 0 16 16"
15+
fill="none"
4416
>
45-
<svg
46-
xmlns="http://www.w3.org/2000/svg"
47-
width="16"
48-
height="16"
49-
viewBox="0 0 16 16"
50-
fill="none"
51-
>
52-
<path d="M8 2L8 11" stroke="#222222" />
53-
<path d="M3.75 7L7.99264 11.2426L12.2353 7" stroke="#222222" />
54-
<path d="M1 12V15H15V12" stroke="#222222" />
55-
</svg>
56-
</a>
17+
<path d="M8 2L8 11" stroke="currentColor" />
18+
<path d="M3.75 7L7.99264 11.2426L12.2353 7" stroke="currentColor" />
19+
<path d="M1 12V15H15V12" stroke="currentColor" />
20+
</svg>
5721
);
5822
};

src/components/buttons/DownloadButton/style.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565

6666
.download-main {
6767
display: flex;
68-
height: 78px;
68+
height: 64px;
6969
padding: 0px 20px;
7070
justify-content: space-between;
7171
align-items: center;
@@ -98,6 +98,7 @@
9898
justify-content: flex-start;
9999
align-items: flex-start;
100100
@include typography(paragraph);
101+
font-size: calc(18px * var(--font-scale-factor));
101102
transition: color 0.2s ease;
102103

103104
p {

src/components/download/DownloadButtonList/DownloadButtonList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type DownloadButtonConfig = {
1212
};
1313

1414
const OWNER = "DefGuard";
15-
const REPO = "client";
15+
const REPO = "defguard";
1616

1717
export const DownloadButtonList = () => {
1818
const [isLoading, setIsLoading] = useState(true);

0 commit comments

Comments
 (0)