mirror of
https://github.com/LukeHagar/developer.sailpoint.com.git
synced 2025-12-06 04:19:31 +00:00
added spinner
This commit is contained in:
16
package-lock.json
generated
16
package-lock.json
generated
@@ -21,6 +21,7 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
|
"react-spinners": "^0.13.8",
|
||||||
"react-tabs": "^4.3.0"
|
"react-tabs": "^4.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -11305,6 +11306,15 @@
|
|||||||
"react": ">=15"
|
"react": ">=15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-spinners": {
|
||||||
|
"version": "0.13.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz",
|
||||||
|
"integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-tabs": {
|
"node_modules/react-tabs": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-4.3.0.tgz",
|
||||||
@@ -21875,6 +21885,12 @@
|
|||||||
"tiny-warning": "^1.0.0"
|
"tiny-warning": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-spinners": {
|
||||||
|
"version": "0.13.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz",
|
||||||
|
"integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"react-tabs": {
|
"react-tabs": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-4.3.0.tgz",
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
|
"react-spinners": "^0.13.8",
|
||||||
"react-tabs": "^4.3.0"
|
"react-tabs": "^4.3.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
@@ -4,23 +4,14 @@ import Link from '@docusaurus/Link';
|
|||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
import ThemedImage from '@theme/ThemedImage';
|
import ThemedImage from '@theme/ThemedImage';
|
||||||
import {addDarkToFileName} from '../../../util/util';
|
import {addDarkToFileName} from '../../../util/util';
|
||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
export default function MarketplaceCard({
|
export default function MarketplaceCard({
|
||||||
link,
|
post,
|
||||||
title,
|
|
||||||
tags,
|
|
||||||
creatorImage,
|
|
||||||
image,
|
|
||||||
excerpt,
|
|
||||||
name,
|
|
||||||
views,
|
|
||||||
replies,
|
|
||||||
readTime,
|
|
||||||
openDialogFunc,
|
openDialogFunc,
|
||||||
rawData
|
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
function setFilters(e) {
|
function setFilters(e) {
|
||||||
openDialogFunc({"rawData": rawData, "title": title, "image": image});
|
openDialogFunc({"rawData": post.raw, "title": post.title, "image": post.image, "link": post.link});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -29,31 +20,29 @@ export default function MarketplaceCard({
|
|||||||
|
|
||||||
<div className={styles.cardData}>
|
<div className={styles.cardData}>
|
||||||
<img className={styles.cardEye} src={useBaseUrl('/blog/eye-regular.svg')}></img>
|
<img className={styles.cardEye} src={useBaseUrl('/blog/eye-regular.svg')}></img>
|
||||||
<div className={styles.cardCommentText}>{views}</div>
|
<div className={styles.cardCommentText}>{post.views}</div>
|
||||||
<img className={styles.cardComment} src={useBaseUrl('/blog/comment-light.svg')}></img>
|
<img className={styles.cardComment} src={useBaseUrl('/blog/comment-light.svg')}></img>
|
||||||
<div className={styles.cardCommentText}>{replies}</div>
|
<div className={styles.cardCommentText}>{post.replies}</div>
|
||||||
<img className={styles.cardComment} src={useBaseUrl('/blog/clock-light.svg')}></img>
|
|
||||||
<div className={styles.cardCommentText}>{readTime} minute read</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.cardUser}>
|
<div className={styles.cardUser}>
|
||||||
<img className={styles.cardFace} src={useBaseUrl(creatorImage)}></img>
|
<img className={styles.cardFace} src={useBaseUrl(post.creatorImage)}></img>
|
||||||
<div className={styles.cardName}>{name}</div>
|
<div className={styles.cardName}>{post.name}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className={styles.cardText}>
|
<div className={styles.cardText}>
|
||||||
<img className={styles.cardImage} src={useBaseUrl(image)}></img>
|
<img className={styles.cardImage} src={useBaseUrl(post.image)}></img>
|
||||||
<div className={styles.cardTitle}>{title}</div>
|
<div className={styles.cardTitle}>{post.title}</div>
|
||||||
<div className={styles.tags}>
|
<div className={styles.tags}>
|
||||||
{tags?.map((tag, index) => {
|
{post.tags?.map((tag, index) => {
|
||||||
if (index > 2) {
|
if (index > 2) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return <div key={tag} className={styles.tag}>{tag}</div>;
|
return <div key={tag} className={styles.tag}>{tag}</div>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.cardBody}>{excerpt}</div>
|
<ReactMarkdown className={styles.cardBody}>{post.excerpt}</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -125,3 +125,4 @@
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ export default function MarketplaceCardDetail({
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goToLink = (link) => {
|
||||||
|
window.open(link, '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.detailContainer}>
|
<div className={styles.detailContainer}>
|
||||||
@@ -40,6 +44,13 @@ export default function MarketplaceCardDetail({
|
|||||||
|
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<ReactMarkdown className={styles.detailTabContent}>{getDivText(details.rawData, "details")}</ReactMarkdown>
|
<ReactMarkdown className={styles.detailTabContent}>{getDivText(details.rawData, "details")}</ReactMarkdown>
|
||||||
|
<button
|
||||||
|
className={styles.modalButton}
|
||||||
|
onClick={async () => {
|
||||||
|
goToLink(details.link);
|
||||||
|
}}>
|
||||||
|
See More
|
||||||
|
</button>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<ReactMarkdown className={styles.detailTabContent}>{getDivText(details.rawData, "requirements")}</ReactMarkdown>
|
<ReactMarkdown className={styles.detailTabContent}>{getDivText(details.rawData, "requirements")}</ReactMarkdown>
|
||||||
|
|||||||
@@ -27,4 +27,27 @@
|
|||||||
|
|
||||||
.detailTabs {
|
.detailTabs {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.modalButton {
|
||||||
|
border: 1px solid var(--ifm-color-primary);
|
||||||
|
box-shadow: 1px 4px 10px rgba(0, 0, 0, 0.12);
|
||||||
|
border-radius: 24px;
|
||||||
|
color: var(--ifm-color-primary);
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100px;
|
||||||
|
background-color: #ffffff31;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalButton:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
top: -2px;
|
||||||
|
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.4);
|
||||||
|
background-color: #dae1e9;
|
||||||
|
color: #005fc4;
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,9 @@ import React from 'react';
|
|||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
import MarketplaceCard from '../MarketplaceCard';
|
import MarketplaceCard from '../MarketplaceCard';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
import BounceLoader from "react-spinners/BounceLoader";
|
||||||
|
|
||||||
|
|
||||||
import {getMarketplacePosts, getMarketplaceTopic, getMarketplaceTopicRaw} from '../../../services/DiscourseService';
|
import {getMarketplacePosts, getMarketplaceTopic, getMarketplaceTopicRaw} from '../../../services/DiscourseService';
|
||||||
import MarketplaceCardDetail from '../MarketplaceCardDetail';
|
import MarketplaceCardDetail from '../MarketplaceCardDetail';
|
||||||
@@ -11,6 +14,7 @@ export default function BlogCards({
|
|||||||
const [cardData, setCardData] = React.useState();
|
const [cardData, setCardData] = React.useState();
|
||||||
const [detailsOpen, setDetailsOpen] = React.useState(false);
|
const [detailsOpen, setDetailsOpen] = React.useState(false);
|
||||||
const [details, setDetails] = React.useState("");
|
const [details, setDetails] = React.useState("");
|
||||||
|
const [loadingCards, setLoadingCards] = React.useState(true);
|
||||||
|
|
||||||
const getPosts = async () => {
|
const getPosts = async () => {
|
||||||
const data = await getMarketplacePosts(filterCallback.join(','));
|
const data = await getMarketplacePosts(filterCallback.join(','));
|
||||||
@@ -23,7 +27,7 @@ export default function BlogCards({
|
|||||||
} else {
|
} else {
|
||||||
setCardData(undefined);
|
setCardData(undefined);
|
||||||
}
|
}
|
||||||
|
setLoadingCards(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
const openDialog = (data) => {
|
const openDialog = (data) => {
|
||||||
@@ -33,6 +37,8 @@ export default function BlogCards({
|
|||||||
Modal.setAppElement('#__docusaurus');
|
Modal.setAppElement('#__docusaurus');
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
getPosts();
|
getPosts();
|
||||||
|
setCardData(undefined);
|
||||||
|
setLoadingCards(true);
|
||||||
}, [filterCallback]);
|
}, [filterCallback]);
|
||||||
|
|
||||||
if (cardData) {
|
if (cardData) {
|
||||||
@@ -41,20 +47,9 @@ export default function BlogCards({
|
|||||||
<div className={styles.gridContainer}>
|
<div className={styles.gridContainer}>
|
||||||
{cardData.map(function(a, index){
|
{cardData.map(function(a, index){
|
||||||
return <MarketplaceCard
|
return <MarketplaceCard
|
||||||
key={a.link}
|
post={a}
|
||||||
id={index + a.link}
|
id={index + a.link}
|
||||||
excerpt={a.excerpt}
|
|
||||||
name={a.name}
|
|
||||||
tags={a.tags}
|
|
||||||
link={a.link}
|
|
||||||
image={a.image}
|
|
||||||
title={a.title}
|
|
||||||
views={a.views}
|
|
||||||
replies={a.replies}
|
|
||||||
readTime={a.readTime}
|
|
||||||
creatorImage={a.creatorImage}
|
|
||||||
openDialogFunc={openDialog}
|
openDialogFunc={openDialog}
|
||||||
rawData={a.raw}
|
|
||||||
></MarketplaceCard>
|
></MarketplaceCard>
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -65,18 +60,26 @@ export default function BlogCards({
|
|||||||
<div>
|
<div>
|
||||||
<MarketplaceCardDetail details={details}></MarketplaceCardDetail>
|
<MarketplaceCardDetail details={details}></MarketplaceCardDetail>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<img className={styles.cardExit} src={useBaseUrl('/icons/circle-xmark-regular.svg')}
|
||||||
className={styles.modalButton}
|
onClick={async () => {
|
||||||
onClick={async () => {
|
setDetailsOpen(false);
|
||||||
setDetailsOpen(false);
|
}}
|
||||||
}}>
|
></img>
|
||||||
OK
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (loadingCards) {
|
||||||
|
return <BounceLoader
|
||||||
|
className={styles.spinnerCenter}
|
||||||
|
color={"#0033a1"}
|
||||||
|
loading={true}
|
||||||
|
size={150}
|
||||||
|
aria-label="Loading Spinner"
|
||||||
|
data-testid="loader"
|
||||||
|
/>
|
||||||
} else {
|
} else {
|
||||||
return <div className={styles.noFound}> No Marketplace Item Found with the Given Search Criteria</div>;
|
return <div className={styles.noFound}> No Marketplace Item Found with the Given Search Criteria</div>;
|
||||||
}
|
}
|
||||||
@@ -89,6 +92,7 @@ async function getPostList(topic) {
|
|||||||
console.log(fullTopic)
|
console.log(fullTopic)
|
||||||
console.log(fullTopicRaw)
|
console.log(fullTopicRaw)
|
||||||
return {
|
return {
|
||||||
|
id: topic.id,
|
||||||
raw: fullTopicRaw,
|
raw: fullTopicRaw,
|
||||||
name: fullTopic.details.created_by.name,
|
name: fullTopic.details.created_by.name,
|
||||||
excerpt: styleExcerpt(topic.excerpt),
|
excerpt: styleExcerpt(topic.excerpt),
|
||||||
@@ -115,6 +119,8 @@ function getavatarURL(avatar) {
|
|||||||
|
|
||||||
function styleExcerpt(excerpt) {
|
function styleExcerpt(excerpt) {
|
||||||
if (excerpt) {
|
if (excerpt) {
|
||||||
|
// remove any strings that have colons between them
|
||||||
|
excerpt = excerpt.replace(/:[^:]*:/g,"")
|
||||||
if (excerpt.length > 150) {
|
if (excerpt.length > 150) {
|
||||||
return excerpt.slice(0, 150) + "..."
|
return excerpt.slice(0, 150) + "..."
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -47,23 +47,32 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButton {
|
|
||||||
border: 1px solid var(--ifm-color-primary);
|
|
||||||
box-shadow: 1px 4px 10px rgba(0, 0, 0, 0.12);
|
|
||||||
border-radius: 24px;
|
|
||||||
color: var(--ifm-color-primary);
|
|
||||||
margin: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
width: 120px;
|
|
||||||
|
|
||||||
background-color: #ffffff31;
|
|
||||||
|
|
||||||
|
.cardExit {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 6px;
|
||||||
|
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: 24px;
|
||||||
|
width: 24px;
|
||||||
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButton:hover {
|
.cardExit:hover {
|
||||||
|
top: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
top: -4px;
|
height: 23px;
|
||||||
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.4);
|
width: 23px;
|
||||||
background-color: #dae1e9;
|
}
|
||||||
color: #005fc4;
|
|
||||||
|
|
||||||
|
.spinnerCenter {
|
||||||
|
margin: 100px auto;
|
||||||
|
max-width: 1300px;
|
||||||
|
margin-bottom: 50px;
|
||||||
}
|
}
|
||||||
1
static/icons/circle-xmark-regular.svg
Normal file
1
static/icons/circle-xmark-regular.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c-9.4 9.4-9.4 24.6 0 33.9l47 47-47 47c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l47-47 47 47c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-47-47 47-47c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-47 47-47-47c-9.4-9.4-24.6-9.4-33.9 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 574 B |
Reference in New Issue
Block a user