Merge pull request #269 from sailpoint-oss/feature/ambassador

Feature/ambassador
This commit is contained in:
Philip Ellis
2023-06-19 16:15:50 -05:00
committed by GitHub
24 changed files with 763 additions and 13 deletions

View File

@@ -0,0 +1,19 @@
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
import useBaseUrl from '@docusaurus/useBaseUrl';
import Link from '@docusaurus/Link';
export default function AmbassadorBanner() {
return (
<div>
<div className={styles.imageContainer}>
<img className={styles.headerImage} src={useBaseUrl('/ambassador/ambassador_banner_template.png')}></img>
<div className={styles.ambassadorHeaderText}>
Ambassadors
</div>
</div >
</div>
);
}

View File

@@ -0,0 +1,28 @@
.ambassadorHeaderText {
position: relative;
color: #ffffff;
font-size: 48px;
max-width: 396px;
font-weight: bold;
line-height: 133%;
top: -84px;
left: 92px;
}
.background {
width: 100%;
object-fit: repeat;
height: 100%;
}
.imageContainer {
width: 100%;
height: 90px;
background: rgb(0,51,161);
background: linear-gradient(90deg, rgba(0,51,161,1) 0%, rgba(84,192,232,1) 100%);
}
.headerImage {
height: 90px;
}

View File

@@ -0,0 +1,38 @@
import React from 'react';
import styles from './styles.module.css';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import ThemedImage from '@theme/ThemedImage';
import {addDarkToFileName} from '../../../util/util';
export default function AmbassadorCard({
data
}) {
return (
<Link to={data.link} className={styles.link}>
<div className={styles.card}>
<div className={styles.cardFaceContainer}>
<img className={styles.cardFace} src={useBaseUrl(data.creatorImage)}></img>
<div className={styles.cardNameContainer}>
<div className={styles.name}>{data.name}</div>
</div>
</div>
<div className={styles.bio} dangerouslySetInnerHTML={{__html: data.bio}}></div>
<div className={styles.cardData}>
<img className={styles.cardEye} src={useBaseUrl('/icons/square-check-regular.svg')}></img>
<div className={styles.cardCommentText}>{data.answers} solutions</div>
</div>
<div className={styles.cardDataLower}>
<img className={styles.cardEye} src={useBaseUrl('/icons/calendar-clock-light.svg')}></img>
<div className={styles.cardCommentText}>member since {data.member_since}</div>
</div>
</div>
</Link>
);
}

View File

@@ -0,0 +1,136 @@
/* Getting Started Card */
.link:hover {
text-decoration: none;
}
.card {
position: relative;
margin-top: 20px;
height: 500px;
max-width: 420px;
/* UI Properties */
background: var(--dev-card-background);
box-shadow: var(--dev-card-shadow);
border: 1px solid var(--dev-card-background);
border-radius: 40px;
opacity: 1;
transition: all 0.3s;
opacity: 1;
}
.card:hover {
cursor: pointer;
transform: translate(0px, -5px);
box-shadow: var(--dev-card-selected);
}
.cardFaceContainer {
display: flex;
margin: 30px;
}
.cardFace {
border-radius: 99px;
justify-content: center;
display: flex;
height: 100px;
width: 100px;
}
.cardNameContainer {
margin-left: 15px;
display: flex;
justify-content: center;
align-items: center;
}
.name {
font-size: 25px;
font-weight: 500;
width: 100%;
top: 124px;
left: 0;
color: var(--dev-text-color-normal);
}
.titleText {
font-size: 10px;
font-weight: 400;
width: 100%;
letter-spacing: 2px;
top: 150px;
left: 0;
color: var(--dev-text-color-normal);
}
.location {
font-size: 10px;
font-weight: 500;
width: 100%;
letter-spacing: 2px;
top: 141px;
left: 0;
color: var(--ifm-color-primary);
}
.cardArrow {
position: absolute;
margin: 20px;
bottom: 5px;
right: 0;
width: 20px;
}
.bio {
position: absolute;
margin: 30px auto;
font-size: 16px;
font-weight: 500;
width: 100%;
top: 100px;
left: 0;
color: var(--ifm-color-primary);
padding: 30px;
}
.cardData {
position: absolute;
bottom: 50px;
left: 20px;
display: flex;
align-items: center;
}
.cardEye {
fill: #96a9bb;
/* computed from codepen https://codepen.io/sosuke/pen/Pjoqqp */
filter: invert(79%) sepia(12%) saturate(484%) hue-rotate(168deg) brightness(84%) contrast(84%);
margin-left: 5px;
height: 18px;
width: 18px;
}
.cardCommentText {
color: #96a9ba;
/* computed from codepen https://codepen.io/sosuke/pen/Pjoqqp */
margin-left: 5px;
margin-bottom: 5px;
height: 20px;
font-size: 16px;
}
.cardDataLower {
position: absolute;
bottom: 20px;
left: 22px;
display: flex;
align-items: center;
}

View File

@@ -0,0 +1,109 @@
import React from 'react';
import styles from './styles.module.css';
import AmbassadorCard from '../AmbassadorCard';
import BounceLoader from 'react-spinners/BounceLoader';
import {getAmbassadors, getAmbassadorDetails} from '../../../services/DiscourseService';
export default function AmbassadorCards({
expert
}) {
const [cardData, setCardData] = React.useState();
const [loadingCards, setLoadingCards] = React.useState(true);
const getPosts = async () => {
const data = await getAmbassadors(expert);
const resultset = []
if (data.members) {
const memberDetails = await getAmbassadorDetails(data.members.map(item => item.id))
for (const member of data.members) {
const memberDetail = memberDetails.users.filter(item => item.id === member.id)[0]
if (member.avatar_template.includes("developer.sailpoint.com") && memberDetail.bio_excerpt && memberDetail.bio_excerpt.length > 60 && memberDetail.accepted_answers > 0) {
resultset.push(await getMemberList(member, memberDetail))
}
}
resultset.sort((a, b) => a.date - b.date)
setCardData(resultset);
} else {
setCardData(undefined);
}
setLoadingCards(false);
};
React.useEffect(() => {
getPosts();
setCardData(undefined);
setLoadingCards(true);
}, []);
if (cardData) {
return (
<div className={styles.center}>
<div className={styles.gridContainer}>
{cardData.map(function(a, index){
return <AmbassadorCard
key={a.link}
data={a}
></AmbassadorCard>
})}
</div>
</div>
);
} else if (loadingCards) {
return (
<BounceLoader
className={styles.spinnerCenter}
color={'#0033a1'}
loading={true}
size={150}
aria-label="Loading Spinner"
data-testid="loader"
/>
);
} else {
return (
<div className={styles.noFound}>
{' '}
No Ambassadors Found with the Given Search Criteria
</div>
);
}
}
async function getMemberList(member, details) {
return {
name: member.name,
creatorImage: getavatarURL(member.avatar_template),
title: member.title,
bio: details.bio_excerpt,
member_since: new Date(member.added_at).toLocaleString('default', {month: 'long'}) + ' ' + new Date(member.added_at).toISOString().slice(0, 4),
badge_count: details.badge_count,
answers: details.accepted_answers,
location: details.location,
website: details.website_name,
link:
'https://developer.sailpoint.com/discuss/u/' +
member.username +
'/summary',
};
}
function getavatarURL(avatar) {
if (avatar.includes("developer.sailpoint.com")) {
return "https://developer.sailpoint.com" + avatar.replace("{size}", "120")
} else {
return avatar.replace("{size}", "120")
}
}
function styleExcerpt(excerpt) {
if (excerpt.length > 150) {
return excerpt.slice(0, 150) + "..."
} else {
return excerpt.replace("&hellip;", "")
}
}

View File

@@ -0,0 +1,35 @@
/* Getting Started Card container */
.gridContainer {
display: grid;
place-content: center;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
grid-gap: 40px;
margin-left: 40px;
margin-right: 40px;
}
.center {
margin: 0px auto;
max-width: 1300px;
margin-bottom: 50px;
}
.space {
height: 200px;
}
.noFound {
font-size: 28px;
font-weight: 500;
color: var(--dev-secondary-text);
padding: 8px;
margin: 50px;
}
.spinnerCenter {
margin: 100px auto;
max-width: 1300px;
margin-bottom: 50px;
}

View File

@@ -47,13 +47,13 @@ export default function BlogSidebar({
if (tagProductData && tagTechnologyData) {
return (
<div className={styles.sidebar}>
<div className={styles.tagHeader}>Posts by Product</div>
<div className={styles.tagHeader}>Blogs by Product</div>
<div className={styles.tagContainer}>
{tagProductData.map(function(a, index){
return <BlogSidebarButton key={a} text={a} filterCallback={filterCallback}></BlogSidebarButton>
})}
</div>
<div className={styles.tagHeader}>Posts by Identity Governance</div>
<div className={styles.tagHeader}>Blogs by Identity Governance</div>
<div className={styles.tagContainer}>
{tagTechnologyData.map(function(a, index){
return <div key={'div' + a} className={index > 10 && filterTags ? styles.hidden : ''} > <BlogSidebarButton key={a} text={a} filterCallback={filterCallback}></BlogSidebarButton></div>

View File

@@ -6,7 +6,7 @@
}
.tagHeader {
margin-top: 10px;
margin-top: 30px;
font-size: 22px;
font-weight: 700;
}

View File

@@ -33,8 +33,9 @@
cursor: pointer;
top: -2px;
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
background-color: #c552ae10;
background-color: var(--dev-button-hover);
color: #cc27b0;
text-decoration: none;
}
.button {
@@ -56,6 +57,7 @@
box-shadow: 0px 20px 60px #00000015;
border: 2px solid #df61ca;
border-radius: 5px;
transition: all 0.3s;
}
.link {
@@ -63,4 +65,5 @@
}
.link:hover {
color: #df61ca;
text-decoration: none;
}

View File

@@ -73,7 +73,7 @@
grid-template-columns: repeat(auto-fit, minmax(520px, 1fr));
/* UI Properties */
background: var(--main-hero-card-background);
box-shadow: var(--dev-card-shadow);
box-shadow: var(--dev-main-card-shadow);
border: 1px solid var(--dev-card-background);
border-radius: 40px;
opacity: 1;

View File

@@ -2,13 +2,14 @@
.gridContainer {
display: grid;
place-content: center;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(195px, 1fr));
grid-gap: 40px;
margin-left: 40px;
margin-right: 40px;
}
.center {
margin: 50px auto;
max-width: 1000px;
margin: 0px auto;
max-width: 1300px;
margin-bottom: 50px;
}

View File

@@ -6,7 +6,7 @@
}
.tagHeader {
margin-top: 10px;
margin-top: 30px;
font-size: 22px;
font-weight: 700;
}

View File

@@ -249,9 +249,11 @@
--text-on-primary: #ffffff;
/*card css*/
--dev-card-background: #ffffff;
--dev-card-shadow: 0px 20px 60px #00000015;
--dev-card-background: #e9e9e963;
--dev-card-shadow: 0px 0px 0px #6b6b6b15;
--dev-main-card-shadow: 0px 20px 60px #00000015;
--dev-card-selected: 0 4px 5px rgba(0, 0, 0, 0.2);
--dev-button-hover: #c552ae10;
--ifm-github-logo: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");
--ifm-medium-logo: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 1770 1000"><circle cx="500" cy="500" r="500"/><ellipse ry="475" rx="250" cy="501" cx="1296"/><ellipse cx="1682" cy="502" rx="88" ry="424"/></svg>');
@@ -284,10 +286,12 @@
/*card css*/
--dev-card-background: #2a2b2d;
--dev-card-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
--dev-card-selected: 0 5px 5px rgba(107, 107, 107, 0.2);
--dev-card-shadow: 0 0px 0px rgba(0, 0, 0, 0.2);
--dev-main-card-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
--dev-card-selected: 0 5px 5px rgba(151, 151, 151, 0.2);
--dev-secondary-text: #dae1e9;
--dev-tag-highlight: #00000075;
--dev-button-hover: #c552ae40;
/*main hero card*/
--main-hero-card-background: #202122;

64
src/pages/ambassador.js Normal file
View File

@@ -0,0 +1,64 @@
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import AmbassadorBanner from '../components/ambassador/AmbassadorBanner';
import useBaseUrl from '@docusaurus/useBaseUrl';
import styles from './ambassador.module.css';
import AmbassadorCards from '../components/ambassador/AmbassadorCards';
export default function Ambassador() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout description="The SailPoint Developer Community has everything you need to build, extend, and automate scalable identity solutions.">
<main>
{/* <AmbassadorBanner /> */}
<div className={styles.ambassadorPurposeContainer}>
<img
className={styles.ambassadorPurposeImage}
src={useBaseUrl('/ambassador/Ambassador-Program-Banner.png')}></img>
<div className={styles.ambassadorPurposeText}>
Our Ambassador Program offers not just exclusive benefits but also
an enriching learning experience on SailPoint; it's a journey to
expertise. As an Ambassador, your contributions foster community
growth, enabling knowledge-sharing among experts like you.
<Link
className={styles.link}
to="https://developer.sailpoint.com/discuss/t/announcing-the-developer-community-ambassador-program/10634">
<div className={styles.button}>Become an Ambassador</div>
</Link>
</div>
</div>
<div className={styles.headerText}>
<div className={styles.headerTextOne}>Expert Ambassadors</div>
</div>
<div className={styles.imageContainer}>
<div className={styles.spanLeft}></div>
<img
className={styles.ambassadorImage}
src={useBaseUrl('/icons/ExpertAmbassador.svg')}></img>
<div className={styles.spanLeft}></div>
</div>
<div className={styles.ambassadorCardContainer}>
<AmbassadorCards expert={true} />
</div>
<div className={styles.headerText}>
<div className={styles.headerTextOne}>Ambassadors</div>
</div>
<div className={styles.imageContainer}>
<div className={styles.spanLeft}></div>
<img
className={styles.ambassadorImage}
src={useBaseUrl('/icons/Ambassador.svg')}></img>
<div className={styles.spanLeft}></div>
</div>
<div className={styles.ambassadorCardContainer}>
<AmbassadorCards expert={false} />
</div>
</main>
</Layout>
);
}

View File

@@ -0,0 +1,142 @@
.gridContainer {
display: grid;
place-content: center;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
grid-gap: 40px;
margin-left: 40px;
margin-right: 40px;
}
.center {
margin: 50px auto;
max-width: 1000px;
}
.headerText {
text-align: center;
display: flex;
margin: 100px auto 0px auto;
width: calc(100% - 100px);
justify-content: center;
}
.headerTextOne {
color: var(--ifm-color-primary);
font-size: 30px;
font-weight: bold;
line-height: 100%;
}
.spanLeft {
width: 35%;
margin: 14px;
position: relative;
top: -45px;
border-bottom-width:2px;
border-bottom-style:solid;
border-bottom-color:var(--ifm-color-primary);
}
.imageContainer {
text-align: center;
display: flex;
justify-content: center;
}
.ambassadorImage {
margin-left: 5px;
padding: 20px;
height: 120px;
width: 120px;
}
.ambassadorPurposeContainer {
display: flex;
justify-content: center;
width: calc(75% + 75px);
align-items: center;
margin: 0px auto 0px auto;
}
.ambassadorPurposeText {
font-size: 21px;
padding: 50px 0px 50px 50px;
font-weight: 500;
color: var(--dev-text-color-normal);
}
.ambassadorPurposeImage {
width: 40%;
box-shadow: var(--dev-card-selected);
border-radius: 40px;
margin: 50px 50px 50px 0px;
}
@media only screen and (max-width: 1460px) {
.ambassadorPurposeContainer {
flex-direction: column;
}
.ambassadorPurposeImage {
width: 80%;
margin: 50px 50px 50px 50px;
}
.ambassadorPurposeText {
padding: 50px 50px 50px 50px;
}
}
.button:hover {
cursor: pointer;
top: -2px;
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
background-color: #c552ae10;
color: #cc27b0;
background-color: var(--dev-button-hover);
}
.button {
text-decoration: none;
text-align: center;
margin: 30px auto;
font-size: 20px;
font-weight: bold;
line-height: 100%;
/* Layout Properties */
width: 314px;
height: 61px;
line-height: 61px;
/* UI Properties */
background: transparent 0% 0% no-repeat padding-box;
opacity: 1;
box-shadow: 0px 20px 60px #00000015;
border: 2px solid #df61ca;
border-radius: 5px;
transition: all 0.3s;
}
.link {
color: #df61ca;
}
.link:hover {
color: #df61ca;
text-decoration: none;
}

View File

@@ -8,6 +8,49 @@ export async function getTopPosts() {
return [];
}
}
export async function getAmbassadors(expert) {
try {
if (expert) {
const response = await fetch(
'https://developer.sailpoint.com/discuss/groups/ambassador_expert/members.json',
);
return await response.json();
} else {
const response = await fetch(
'https://developer.sailpoint.com/discuss/groups/ambassador/members.json',
);
return await response.json();
}
} catch (error) {
return [];
}
}
export async function getAmbassadorDetails(id) {
try {
const response = await fetch(
'https://developer.sailpoint.com/discuss/user-cards.json?user_ids=' + id.join(','),
);
return await response.json();
} catch (error) {
return [];
}
}
export async function checkImage(url) {
try {
const response = await fetch(
url,
);
console.log(response)
return true
} catch (error) {
return false;
}
}
export async function getBlogPosts(tags) {
let url = ''

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 142 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M112 0c8.8 0 16 7.2 16 16V64H320V16c0-8.8 7.2-16 16-16s16 7.2 16 16V64h32c35.3 0 64 28.7 64 64v32 32 .7c-5.3-.5-10.6-.7-16-.7s-10.7 .2-16 .7V192H32V448c0 17.7 14.3 32 32 32H296.2c10 12.1 21.7 22.9 34.6 32H64c-35.3 0-64-28.7-64-64V192 160 128C0 92.7 28.7 64 64 64H96V16c0-8.8 7.2-16 16-16zM384 96H64c-17.7 0-32 14.3-32 32v32H416V128c0-17.7-14.3-32-32-32zm48 384a112 112 0 1 0 0-224 112 112 0 1 0 0 224zm0-256a144 144 0 1 1 0 288 144 144 0 1 1 0-288zm0 64c8.8 0 16 7.2 16 16v48h32c8.8 0 16 7.2 16 16s-7.2 16-16 16H432c-8.8 0-16-7.2-16-16V304c0-8.8 7.2-16 16-16z"/></svg>

After

Width:  |  Height:  |  Size: 807 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 80c-8.8 0-16 7.2-16 16V416c0 8.8 7.2 16 16 16H384c8.8 0 16-7.2 16-16V96c0-8.8-7.2-16-16-16H64zM0 96C0 60.7 28.7 32 64 32H384c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM337 209L209 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L303 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/></svg>

After

Width:  |  Height:  |  Size: 595 B