Skip to content

Commit

Permalink
Merge pull request #2146 from amvanbaren/feature/issue-773
Browse files Browse the repository at this point in the history
Show Adopters of Open VSX on the Website
amvanbaren authored Oct 16, 2023
2 parents b4a73b6 + 30ea13b commit be987ba
Showing 7 changed files with 298 additions and 37 deletions.
2 changes: 1 addition & 1 deletion configuration/application.yml
Original file line number Diff line number Diff line change
@@ -129,7 +129,7 @@ ovsx:
storage:
primary-service: azure-blob
webui:
frontendRoutes: "/extension/**,/namespace/**,/user-settings/**,/admin-dashboard/**,/about,/publisher-agreement-*,/terms-of-use,/members"
frontendRoutes: "/extension/**,/namespace/**,/user-settings/**,/admin-dashboard/**,/about,/publisher-agreement-*,/terms-of-use,/members,/adopters"
eclipse:
# TODO change back to https://api.eclipse.org/ for release.
base-url: https://api-staging.eclipse.org/
2 changes: 1 addition & 1 deletion website/dev/mock-service.ts
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import {
NamespaceMembershipList, AdminService, PublisherInfo, NewReview, ExtensionFilter, UrlString, MembershipRole
} from "openvsx-webui";

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

export class MockRegistryService extends ExtensionRegistryService {

25 changes: 19 additions & 6 deletions website/src/about.tsx
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
********************************************************************************/

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

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

<Heading variant='h5'>Publishing Extensions</Heading>
<Paragraph variant='body1'>
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>.
</Paragraph>
<Heading variant='h5'>Resources</Heading>
<List>
<ListItem>
<ListItemText>
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>.
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
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.
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
Get involved in the <Link color='secondary' underline='hover' href='https://gitter.im/eclipse/openvsx'>community</Link>.
</ListItemText>
</ListItem>
</List>
</Container>;
}

34 changes: 34 additions & 0 deletions website/src/adopters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import { Container, Typography, Box, Button } from "@mui/material";
import { styled, Theme } from '@mui/material/styles';
import AdoptersList from "./components/adopters-list";

const Heading = styled(Typography)(({ theme }: { theme: Theme }) => ({
marginTop: theme.spacing(4),
marginBottom: theme.spacing(2)
}));

const Adopters = () => {
return (
<Container maxWidth='md'>
<Heading variant='h4'>
Adopters
</Heading>
<Typography>
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.
</Typography>
<AdoptersList/>
<Box mt={4} textAlign='center'>
<Button
variant='contained'
color='secondary'
href='https://ecdtools.eclipse.org/adopters/get-listed/'
>
Get Listed
</Button>
</Box>
</Container>
);
}

export default Adopters;
163 changes: 163 additions & 0 deletions website/src/components/adopters-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/********************************************************************************
* Copyright (c) 2023 TypeFox and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/

import React, { FunctionComponent, useState, useEffect, useContext } from 'react';
import { CircularProgress, Grid, Box, Link, Typography } from '@mui/material';
import { styled, Theme } from '@mui/material/styles';
import { MainContext } from 'openvsx-webui/lib/context';

interface Project {
project_id: string;
name: string;
url: string;
logo: string;
adopters: Adopter[];
}

interface Adopter {
name: string;
logo: string;
projects: string[];
homepage_url: string;
logo_white: string;
}

const AdoptersList: FunctionComponent = () => {
const [loaded, setLoaded] = useState(false);
const [adopters, setAdopters] = useState<Adopter[]>([]);

useEffect(() => {
if (loaded) return;

const abortController = new AbortController();
fetch(`https://api.eclipse.org/adopters/projects?working_group=cloud-development-tools`, {
signal: abortController.signal,
})
.then(async (res) => {
if (!res.ok) throw new Error('Failed to fetch adopters');

const projects = await res.json() as Project[];
const project = projects.find((p) => p.project_id == 'ecd.openvsx');
if(project) {
setAdopters(project.adopters);
}
})
.catch((err) => {
if (err instanceof DOMException && err.name === 'AbortError') return;
console.error(err);
})
.finally(() => abortController.signal.aborted || setLoaded(true));

return () => abortController.abort();
}, [loaded]);

if (adopters.length === 0) return <CircularProgress />;
return (
<Grid container spacing={3} mt={2}>
{ adopters.map(adopter =>
<AdopterItem
key={adopter.name}
name={adopter.name}
logo={adopter.logo}
logoWhite={adopter.logo_white}
url={adopter.homepage_url}
/>
)}
</Grid>
);
};

export default AdoptersList;

interface AdopterItemProps {
name: string;
logo?: string;
logoWhite?: string;
url?: string;
}

const bordered = (theme: Theme) => {
return {
border: '1px solid',
borderColor: theme.palette.mode === 'light'
? theme.palette.grey['300']
: theme.palette.grey['800']
};
};

const HeaderBox = styled(Box)(({ theme }: { theme: Theme }) => ({
...bordered(theme),
display: 'flex',
alignItems: 'center',
minHeight: '6rem',
backgroundColor: theme.palette.mode === 'light'
? theme.palette.grey['300']
: theme.palette.grey['800']
}));

const BodyBox = styled(Box)(({ theme }: { theme: Theme }) => ({
...bordered(theme),
display: 'flex',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme.palette.background.default
}));

const GridContainer = styled(Grid)({
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
height: '18rem',
textAlign: 'center',
});

const AdopterItem: FunctionComponent<AdopterItemProps> = ({ name, logo, logoWhite, url }) => {
const { pageSettings } = useContext(MainContext);
const styles = {
heading: {
width: '100%',
},
logoContainer: {
width: '100%',
maxWidth: '8rem',
maxHeight: '8rem',
},
logo: {
width: '100%',
height: '100%',
objectFit: 'contain',
}
};

let logoUrl = pageSettings.themeType == 'dark' ? logoWhite : logo;
if(logoUrl) {
logoUrl = 'https://api.eclipse.org/adopters/assets/images/adopters/' + logoUrl;
}

return (
<GridContainer item xs={12} md={4}>
<HeaderBox p={2}>
{ url
? <Link sx={styles.heading} href={url} variant="h6">{name}</Link>
: <Typography sx={styles.heading} variant="h6">{name}</Typography>
}
</HeaderBox>
<BodyBox p={2}>
<Box sx={styles.logoContainer}>
{ logoUrl
? <Box component='img' sx={styles.logo} src={logoUrl} alt='' />
: <Typography variant='h6'>{name}</Typography>
}
</Box>
</BodyBox>
</GridContainer>
);
};
107 changes: 78 additions & 29 deletions website/src/menu-content.tsx
Original file line number Diff line number Diff line change
@@ -8,18 +8,20 @@
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/

import React, { FunctionComponent, PropsWithChildren } from 'react';
import { Theme, Typography, MenuItem, Link, Button } from '@mui/material';
import React, { FunctionComponent, PropsWithChildren, useState, useRef } from 'react';
import { Theme, Typography, Menu, MenuItem, Link, Button, Accordion, AccordionDetails, AccordionSummary } from '@mui/material';
import { styled } from '@mui/material/styles';
import { Link as RouteLink } from 'react-router-dom';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import GitHubIcon from '@mui/icons-material/GitHub';
import MenuBookIcon from '@mui/icons-material/MenuBook';
import HelpIcon from '@mui/icons-material/Help';
import ForumIcon from '@mui/icons-material/Forum';
import InfoIcon from '@mui/icons-material/Info';
import StarIcon from '@mui/icons-material/Star';
import StatusIcon from '@mui/icons-material/NetworkCheck';
import PublishIcon from '@mui/icons-material/Publish';
import GroupWorkIcon from '@mui/icons-material/GroupWork';
import PeopleAltIcon from '@mui/icons-material/PeopleAlt';
import HubIcon from '@mui/icons-material/Hub';
import { UserSettingsRoutes } from 'openvsx-webui';

//-------------------- Mobile View --------------------//
@@ -71,19 +73,41 @@ export const MobileMenuContent: FunctionComponent = () => {
</MobileMenuItemText>
</Link>
</MobileMenuItem>
<MobileMenuItem>
<Link href='https://www.eclipse.org/legal/open-vsx-registry-faq/'>
<Accordion sx={{border: 0, borderRadius: 0, boxShadow: '0 0'}}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="working-group-content"
id="working-group-header"
>
<MobileMenuItemText>
<HelpIcon sx={itemIcon} />
FAQ
<GroupWorkIcon sx={itemIcon} />
Working Group
</MobileMenuItemText>
</Link>
</MobileMenuItem>
</AccordionSummary>
<AccordionDetails>
<MobileMenuItem>
<RouteLink to='/members'>
<MobileMenuItemText>
<PeopleAltIcon sx={itemIcon} />
Members
</MobileMenuItemText>
</RouteLink>
</MobileMenuItem>
<MobileMenuItem>
<RouteLink to='/adopters'>
<MobileMenuItemText>
<HubIcon sx={itemIcon} />
Adopters
</MobileMenuItemText>
</RouteLink>
</MobileMenuItem>
</AccordionDetails>
</Accordion>
<MobileMenuItem>
<Link href='https://gitter.im/eclipse/openvsx'>
<Link href='https://www.eclipse.org/donate/openvsx/'>
<MobileMenuItemText>
<ForumIcon sx={itemIcon} />
Community
<StarIcon sx={itemIcon} />
Sponsor
</MobileMenuItemText>
</Link>
</MobileMenuItem>
@@ -95,14 +119,6 @@ export const MobileMenuContent: FunctionComponent = () => {
</MobileMenuItemText>
</RouteLink>
</MobileMenuItem>
<MobileMenuItem>
<Link href='https://www.eclipse.org/donate/openvsx/'>
<MobileMenuItemText>
<StarIcon sx={itemIcon} />
Sponsor
</MobileMenuItemText>
</Link>
</MobileMenuItem>
{
!location.pathname.startsWith(UserSettingsRoutes.ROOT)
? <MobileMenuItem>
@@ -135,29 +151,62 @@ const headerItem = ({ theme }: { theme: Theme }) => ({
}
});

const headerTypography = ({ theme }: { theme: Theme }) => ({
...headerItem({theme}),
cursor: 'pointer'
});

const MenuLink = styled(Link)(headerItem);
const MenuRouteLink = styled(RouteLink)(headerItem);
const MenuTypography = styled(Typography)(headerTypography);

const subMenuItem = ({ theme }: { theme: Theme }) => ({
'&:focus, &:hover': {
background: 'transparent'
}
});

const subMenuLink = ({ theme }: { theme: Theme }) => ({
...headerItem({theme}),
margin: theme.spacing(0.5)
});

const SubMenuItem = styled(MenuItem)(subMenuItem);
const SubMenuLink = styled(Link)(subMenuLink);


export const DefaultMenuContent: FunctionComponent = () => {
const [workingGroupMenuOpen, setWorkingGroupOpen] = useState(false);
const workingGroupMenuEl = useRef<HTMLButtonElement | null>(null);
const toggleWorkingGroupMenu = () => setWorkingGroupOpen(!workingGroupMenuOpen);
const closeWorkingGroupMenu = () => setWorkingGroupOpen(false);

return <>
<MenuLink href='https://github.com/eclipse/openvsx/wiki'>
Documentation
</MenuLink>
<MenuLink href='https://www.eclipse.org/legal/open-vsx-registry-faq/'>
FAQ
</MenuLink>
<MenuLink href='https://status.open-vsx.org/'>
Status
</MenuLink>
<MenuLink href='https://gitter.im/eclipse/openvsx'>
Community
<MenuTypography onClick={toggleWorkingGroupMenu} ref={workingGroupMenuEl}>Working Group</MenuTypography>
<Menu open={workingGroupMenuOpen} onClose={closeWorkingGroupMenu} anchorEl={workingGroupMenuEl.current}>
<SubMenuItem>
<SubMenuLink href='/members' onClick={closeWorkingGroupMenu}>
Members
</SubMenuLink>
</SubMenuItem>
<SubMenuItem>
<SubMenuLink href='/adopters' onClick={closeWorkingGroupMenu}>
Adopters
</SubMenuLink>
</SubMenuItem>
</Menu>
<MenuLink href='https://www.eclipse.org/donate/openvsx/'>
Sponsor
</MenuLink>
<MenuRouteLink to='/about'>
About
</MenuRouteLink>
<MenuLink href='https://www.eclipse.org/donate/openvsx/'>
Sponsor
</MenuLink>
<Button variant='contained' color='secondary' href='/user-settings/extensions' sx={{ mx: 2.5 }}>
Publish
</Button>
2 changes: 2 additions & 0 deletions website/src/page-settings.tsx
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import OpenVSXLogo from './openvsx-registry-logo';
import footerContent from './footer-content';
import { Document } from './document';
import About from './about';
import Adopters from './adopters';
import Members from './members';

export default function createPageSettings(theme: Theme, prefersDarkMode: boolean): PageSettings {
@@ -64,6 +65,7 @@ export default function createPageSettings(theme: Theme, prefersDarkMode: boolea
<Route path='/terms-of-use' element={<Document url='/documents/terms-of-use.md' />} />
<Route path='/publisher-agreement-v1.0' element={<Document url='/documents/publisher-agreement-v1.0.md' />} />
<Route path='/members' element={<Members />} />
<Route path='/adopters' element={<Adopters />} />
</>;

//---------- REPORT ABUSE LINK

0 comments on commit be987ba

Please sign in to comment.