Skip to content

Commit 30ea13b

Browse files
author
amvanbaren
committed
Show Adopters of Open VSX on the Website
Add adopters page Add 'Working Group' menu item to header menu Remove 'Community' and 'FAQ' menu items from header menu Add Resources section to About page with links to Community and FAQ
1 parent b4a73b6 commit 30ea13b

File tree

7 files changed

+298
-37
lines changed

7 files changed

+298
-37
lines changed

configuration/application.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ ovsx:
129129
storage:
130130
primary-service: azure-blob
131131
webui:
132-
frontendRoutes: "/extension/**,/namespace/**,/user-settings/**,/admin-dashboard/**,/about,/publisher-agreement-*,/terms-of-use,/members"
132+
frontendRoutes: "/extension/**,/namespace/**,/user-settings/**,/admin-dashboard/**,/about,/publisher-agreement-*,/terms-of-use,/members,/adopters"
133133
eclipse:
134134
# TODO change back to https://api.eclipse.org/ for release.
135135
base-url: https://api-staging.eclipse.org/

website/dev/mock-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
NamespaceMembershipList, AdminService, PublisherInfo, NewReview, ExtensionFilter, UrlString, MembershipRole
1515
} from "openvsx-webui";
1616

17-
const avatarUrl = 'https://upload.wikimedia.org/wikipedia/commons/1/19/Spongebob_Squarepants_as_a_balloon.jpg';
17+
const avatarUrl = 'https://upload.wikimedia.org/wikipedia/commons/9/99/Avatar_cupcake.png';
1818

1919
export class MockRegistryService extends ExtensionRegistryService {
2020

website/src/about.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
********************************************************************************/
1010

1111
import * as React from 'react';
12-
import { Link, Typography, Container } from '@mui/material';
12+
import { Link, Typography, Container, List, ListItem, ListItemText } from '@mui/material';
1313
import { styled, Theme } from '@mui/material/styles';
1414

1515
const Heading = styled(Typography)(({ theme }: { theme: Theme }) => ({
@@ -58,11 +58,24 @@ const About = () => {
5858
</li>
5959
</RepositoryList>
6060

61-
<Heading variant='h5'>Publishing Extensions</Heading>
62-
<Paragraph variant='body1'>
63-
The publishing process is described in
64-
the <Link color='secondary' underline='hover' href='https://github.com/eclipse/openvsx/wiki/Publishing-Extensions#how-to-publish-an-extension'>openvsx Wiki</Link>.
65-
</Paragraph>
61+
<Heading variant='h5'>Resources</Heading>
62+
<List>
63+
<ListItem>
64+
<ListItemText>
65+
The publishing process is described in the <Link color='secondary' underline='hover' href='https://github.com/eclipse/openvsx/wiki/Publishing-Extensions#how-to-publish-an-extension'>openvsx Wiki</Link>.
66+
</ListItemText>
67+
</ListItem>
68+
<ListItem>
69+
<ListItemText>
70+
The <Link color='secondary' underline='hover' href='https://www.eclipse.org/legal/open-vsx-registry-faq/'>FAQ</Link> section explains what you can and cannot do as a user of our service.
71+
</ListItemText>
72+
</ListItem>
73+
<ListItem>
74+
<ListItemText>
75+
Get involved in the <Link color='secondary' underline='hover' href='https://gitter.im/eclipse/openvsx'>community</Link>.
76+
</ListItemText>
77+
</ListItem>
78+
</List>
6679
</Container>;
6780
}
6881

website/src/adopters.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from "react";
2+
import { Container, Typography, Box, Button } from "@mui/material";
3+
import { styled, Theme } from '@mui/material/styles';
4+
import AdoptersList from "./components/adopters-list";
5+
6+
const Heading = styled(Typography)(({ theme }: { theme: Theme }) => ({
7+
marginTop: theme.spacing(4),
8+
marginBottom: theme.spacing(2)
9+
}));
10+
11+
const Adopters = () => {
12+
return (
13+
<Container maxWidth='md'>
14+
<Heading variant='h4'>
15+
Adopters
16+
</Heading>
17+
<Typography>
18+
Our open source projects drive innovation across a broad spectrum of industries and on both private and public clouds — enabling organizations of all shapes and sizes to accelerate cloud native development with world-class tools.
19+
</Typography>
20+
<AdoptersList/>
21+
<Box mt={4} textAlign='center'>
22+
<Button
23+
variant='contained'
24+
color='secondary'
25+
href='https://ecdtools.eclipse.org/adopters/get-listed/'
26+
>
27+
Get Listed
28+
</Button>
29+
</Box>
30+
</Container>
31+
);
32+
}
33+
34+
export default Adopters;
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/********************************************************************************
2+
* Copyright (c) 2023 TypeFox and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
11+
import React, { FunctionComponent, useState, useEffect, useContext } from 'react';
12+
import { CircularProgress, Grid, Box, Link, Typography } from '@mui/material';
13+
import { styled, Theme } from '@mui/material/styles';
14+
import { MainContext } from 'openvsx-webui/lib/context';
15+
16+
interface Project {
17+
project_id: string;
18+
name: string;
19+
url: string;
20+
logo: string;
21+
adopters: Adopter[];
22+
}
23+
24+
interface Adopter {
25+
name: string;
26+
logo: string;
27+
projects: string[];
28+
homepage_url: string;
29+
logo_white: string;
30+
}
31+
32+
const AdoptersList: FunctionComponent = () => {
33+
const [loaded, setLoaded] = useState(false);
34+
const [adopters, setAdopters] = useState<Adopter[]>([]);
35+
36+
useEffect(() => {
37+
if (loaded) return;
38+
39+
const abortController = new AbortController();
40+
fetch(`https://api.eclipse.org/adopters/projects?working_group=cloud-development-tools`, {
41+
signal: abortController.signal,
42+
})
43+
.then(async (res) => {
44+
if (!res.ok) throw new Error('Failed to fetch adopters');
45+
46+
const projects = await res.json() as Project[];
47+
const project = projects.find((p) => p.project_id == 'ecd.openvsx');
48+
if(project) {
49+
setAdopters(project.adopters);
50+
}
51+
})
52+
.catch((err) => {
53+
if (err instanceof DOMException && err.name === 'AbortError') return;
54+
console.error(err);
55+
})
56+
.finally(() => abortController.signal.aborted || setLoaded(true));
57+
58+
return () => abortController.abort();
59+
}, [loaded]);
60+
61+
if (adopters.length === 0) return <CircularProgress />;
62+
return (
63+
<Grid container spacing={3} mt={2}>
64+
{ adopters.map(adopter =>
65+
<AdopterItem
66+
key={adopter.name}
67+
name={adopter.name}
68+
logo={adopter.logo}
69+
logoWhite={adopter.logo_white}
70+
url={adopter.homepage_url}
71+
/>
72+
)}
73+
</Grid>
74+
);
75+
};
76+
77+
export default AdoptersList;
78+
79+
interface AdopterItemProps {
80+
name: string;
81+
logo?: string;
82+
logoWhite?: string;
83+
url?: string;
84+
}
85+
86+
const bordered = (theme: Theme) => {
87+
return {
88+
border: '1px solid',
89+
borderColor: theme.palette.mode === 'light'
90+
? theme.palette.grey['300']
91+
: theme.palette.grey['800']
92+
};
93+
};
94+
95+
const HeaderBox = styled(Box)(({ theme }: { theme: Theme }) => ({
96+
...bordered(theme),
97+
display: 'flex',
98+
alignItems: 'center',
99+
minHeight: '6rem',
100+
backgroundColor: theme.palette.mode === 'light'
101+
? theme.palette.grey['300']
102+
: theme.palette.grey['800']
103+
}));
104+
105+
const BodyBox = styled(Box)(({ theme }: { theme: Theme }) => ({
106+
...bordered(theme),
107+
display: 'flex',
108+
height: '100%',
109+
alignItems: 'center',
110+
justifyContent: 'center',
111+
backgroundColor: theme.palette.background.default
112+
}));
113+
114+
const GridContainer = styled(Grid)({
115+
display: 'flex',
116+
flexDirection: 'column',
117+
alignItems: 'stretch',
118+
height: '18rem',
119+
textAlign: 'center',
120+
});
121+
122+
const AdopterItem: FunctionComponent<AdopterItemProps> = ({ name, logo, logoWhite, url }) => {
123+
const { pageSettings } = useContext(MainContext);
124+
const styles = {
125+
heading: {
126+
width: '100%',
127+
},
128+
logoContainer: {
129+
width: '100%',
130+
maxWidth: '8rem',
131+
maxHeight: '8rem',
132+
},
133+
logo: {
134+
width: '100%',
135+
height: '100%',
136+
objectFit: 'contain',
137+
}
138+
};
139+
140+
let logoUrl = pageSettings.themeType == 'dark' ? logoWhite : logo;
141+
if(logoUrl) {
142+
logoUrl = 'https://api.eclipse.org/adopters/assets/images/adopters/' + logoUrl;
143+
}
144+
145+
return (
146+
<GridContainer item xs={12} md={4}>
147+
<HeaderBox p={2}>
148+
{ url
149+
? <Link sx={styles.heading} href={url} variant="h6">{name}</Link>
150+
: <Typography sx={styles.heading} variant="h6">{name}</Typography>
151+
}
152+
</HeaderBox>
153+
<BodyBox p={2}>
154+
<Box sx={styles.logoContainer}>
155+
{ logoUrl
156+
? <Box component='img' sx={styles.logo} src={logoUrl} alt='' />
157+
: <Typography variant='h6'>{name}</Typography>
158+
}
159+
</Box>
160+
</BodyBox>
161+
</GridContainer>
162+
);
163+
};

0 commit comments

Comments
 (0)