Skip to content

Commit

Permalink
Feature/dron 101 (#391)
Browse files Browse the repository at this point in the history
adaptive cards work
  • Loading branch information
Dan Wilson authored Nov 4, 2021
1 parent f0c4109 commit 774d83a
Show file tree
Hide file tree
Showing 14 changed files with 4,226 additions and 3,851 deletions.
7,782 changes: 3,955 additions & 3,827 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@
},
"dependencies": {
"@emotion/core": "^10.1.1",
"@emotion/react": "^11.5.0",
"@emotion/styled": "^10.0.27",
"@monaco-editor/react": "^4.2.2",
"@projectstorm/react-diagrams": "^6.0.1-beta.7",
"adaptive-expressions": "^4.14.1",
"adaptivecards": "^2.10.0",
"adaptivecards-templating": "^2.1.0",
"ansi_up": "^4.0.4",
"axios": "^0.21.0",
"axios": "^0.21.4",
"classnames": "^2.2.6",
"closest": "0.0.1",
"dagre": "^0.8.5",
"date-fns": "^2.16.1",
"immer": "^9.0.3",
"immer": "^9.0.6",
"lodash": "^4.17.21",
"normalize.css": "^8.0.1",
"pathfinding": "^0.4.18",
Expand Down
63 changes: 63 additions & 0 deletions src/components/pages/build/cards-view/card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Template } from 'adaptivecards-templating';
import axios from 'axios';
import classNames from 'classnames/bind';
import PropTypes from 'prop-types';
import React, { useEffect, useState } from 'react';

import { useCard } from 'hooks/swr';

import AdaptiveCard from '../../../shared/adaptive-card';

import css from './card.module.scss';

const cx = classNames.bind(css);

const loadAdaptiveCard = async (url, json, setAdaptiveCard) => {
const schema = await axios({ method: 'GET', url });
const template = new Template(schema?.data);
const cardPayload = await template.expand({
$root: {
...json,
},
});
setAdaptiveCard(cardPayload);
};

const Card = ({
data, namespace, name, build,
}) => {
const {
data: json, isError: jsonIsError, isLoading: jsonIsLoading,
} = useCard({
namespace, name, build, stage: data.stage, step: data.step,
});

const [adaptiveCard, setAdaptiveCard] = useState(null);

useEffect(() => {
if (!jsonIsLoading && !adaptiveCard) {
loadAdaptiveCard(data.schema, json, setAdaptiveCard);
}
}, [jsonIsLoading, data, json, adaptiveCard]);

if (jsonIsLoading || !adaptiveCard) {
return <li className={cx('card', 'card-message')}>CARD LOADING...</li>;
}
if (jsonIsError) {
return <li className={cx('card', 'card-message')}>CARD ERROR</li>;
}
return <li className={cx('card')}><AdaptiveCard payload={adaptiveCard} /></li>;
};

Card.propTypes = {
namespace: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
build: PropTypes.string.isRequired,
data: PropTypes.shape({
schema: PropTypes.string.isRequired,
stage: PropTypes.number.isRequired,
step: PropTypes.number.isRequired,
}).isRequired,
};

export default Card;
11 changes: 11 additions & 0 deletions src/components/pages/build/cards-view/card.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.card {
background-color: white;
display: flex;
align-items: center;
margin: 0 0 1rem 0;
border: 1px lightgrey solid;

&-message {
padding: 1rem;
}
}
46 changes: 46 additions & 0 deletions src/components/pages/build/cards-view/cards-view.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import classNames from 'classnames/bind';
import PropTypes from 'prop-types';
import React from 'react';

import Card from './card';
import css from './cards-view.module.scss';

const cx = classNames.bind(css);

const CardsView = ({
data, isDataLoading, namespace, name, build,
}) => {
if (isDataLoading) {
return <div className={cx('message')}>LOADING...</div>;
} if (!data.length) {
return <div className={cx('card-list')}><span className={cx('message')}>NO ADAPTIVE CARDS FOUND</span></div>;
}
return (
<ul className={cx('card-list')}>
{data?.map((cardData) => {
// causes a weird error when I use template literals...
// eslint-disable-next-line prefer-template
const key = cardData.stage.toString() + ' - ' + cardData.step.toString();
return <Card key={key} data={cardData} namespace={namespace} name={name} build={build} />;
})}
</ul>
);
};

CardsView.propTypes = {
data: PropTypes.arrayOf(PropTypes.shape({
schema: PropTypes.string.isRequired,
stage: PropTypes.number.isRequired,
step: PropTypes.number.isRequired,
})),
isDataLoading: PropTypes.bool.isRequired,
namespace: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
build: PropTypes.string.isRequired,
};

CardsView.defaultProps = {
data: [],
};

export default CardsView;
12 changes: 12 additions & 0 deletions src/components/pages/build/cards-view/cards-view.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.card-list {
margin: 1rem 2rem;
display: flex;
flex-direction: column;
align-items: center;
}

.message {
padding: 1rem;
background-color: white;
border: 1px lightgrey solid;
}
1 change: 1 addition & 0 deletions src/components/pages/build/cards-view/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './cards-view';
25 changes: 25 additions & 0 deletions src/components/shared/adaptive-card/adaptive-card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable no-unused-expressions */
import { AdaptiveCard } from 'adaptivecards';
import PropTypes from 'prop-types';
import React from 'react';

const AdaptiveCardComponent = ({ payload }) => {
const adaptiveCard = new AdaptiveCard();

adaptiveCard.parse(payload);
const result = adaptiveCard.render();
return (
<div
ref={(n) => {
n && n.firstChild && n.removeChild(n.firstChild);
n && n.appendChild(result);
}}
/>
);
};

AdaptiveCardComponent.propTypes = {
payload: PropTypes.shape().isRequired,
};

export default AdaptiveCardComponent;
1 change: 1 addition & 0 deletions src/components/shared/adaptive-card/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './adaptive-card';
5 changes: 5 additions & 0 deletions src/hooks/swr/cards.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import useSWRBase from './use-swr-base';

export const useCard = ({
namespace, name, build, stage, step,
}) => useSWRBase(`/api/repos/${namespace}/${name}/cards/${build}/${stage}/${step}`);
2 changes: 2 additions & 0 deletions src/hooks/swr/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
useBuild, useBuilds, useStreamBuildEvents, updateBuilds,
} from './builds';
import { useCard } from './cards';
import { useLogs, useStreamLogs } from './logs';
import { useRepo, useLatestRepos } from './repo';
import useBranches from './use-branches';
Expand All @@ -23,6 +24,7 @@ export {
useRepo,
useSecrets,
useOrgSecrets,
useCard,
useCrons,
useViewerToken,
useViewer,
Expand Down
74 changes: 60 additions & 14 deletions src/pages/build/build.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import classNames from 'classnames/bind';
import PropTypes from 'prop-types';
import React, {
useCallback, useState, useLayoutEffect,
} from 'react';
import { useHistory, useParams } from 'react-router-dom';

import { instance } from '_constants';
import CardsView from 'components/pages/build/cards-view';
import GraphView from 'components/pages/build/graph-view';
import LogView from 'components/pages/build/log-view';
import { NonLogsContainer } from 'components/pages/build/log-view/console-manager';
Expand All @@ -26,6 +28,41 @@ const ERROR = 'error';
const RESOLVED = 'resolved';
const RESOLVED_BLOCKED = 'resolved_blocked';

const LOGS_VIEW = 'logs';
const GRAPH_VIEW = 'graph';
const CARDS_VIEW = 'cards';

export const VIEWS = { LOGS_VIEW, GRAPH_VIEW, CARDS_VIEW };

const getContent = (view, data, isLoading, namespace, name, build, cardsData) => {
switch (view) {
case GRAPH_VIEW:
return (
<GraphView
data={data}
isDataLoading={isLoading}
/>
);
case CARDS_VIEW:
return (
<CardsView
data={cardsData}
isDataLoading={isLoading}
namespace={namespace}
name={name}
build={build}
/>
);
default:
return (
<LogView
data={data}
isDataLoading={isLoading}
/>
);
}
};

export default function Build({ user, userIsAdminOrHasWritePerm }) {
const params = useParams();
const {
Expand All @@ -38,7 +75,7 @@ export default function Build({ user, userIsAdminOrHasWritePerm }) {
data, mutate, isError, isLoading,
} = useBuild({ namespace, name, build });
const [state, setState] = useState(RESOLVED);
const [isGraphView, setIsGraphView] = useLocalStorage('isBuildPageInGraphMode', false);
const [view, setView] = useLocalStorage('buildPageView', LOGS_VIEW);

const [isModalShowing, toggleModal] = useModal();

Expand All @@ -58,7 +95,20 @@ export default function Build({ user, userIsAdminOrHasWritePerm }) {
}
}, [data, isError, isLoading, stage]);

const handleViewModeClick = (mode) => () => setIsGraphView(mode === 'graph');
// sort individual steps card data into a managable array
const cardsData = data?.stages?.reduce((cardDataAcc, stageData) => {
const stageCardData = stageData?.steps?.reduce((stageDataAcc, stepData) => {
if (stepData.schema) {
return [...stageDataAcc, {
stage: stageData.number, step: stepData.number, schema: stepData.schema,
}];
}
return stageDataAcc;
}, []) || [];
return [...cardDataAcc, ...stageCardData];
}, []);

const handleViewModeClick = (mode) => () => setView(mode);

const handleDeploySubmit = useCallback(async ({ action, target, parameters }) => {
const queryParams = parameters
Expand Down Expand Up @@ -211,26 +261,17 @@ export default function Build({ user, userIsAdminOrHasWritePerm }) {
break;
case RESOLVED:
default:
content = isGraphView ? (
<GraphView
data={data}
isDataLoading={isLoading}
/>
) : (
<LogView
data={data}
isDataLoading={isLoading}
/>
);
content = getContent(view, data, isLoading, namespace, name, build, cardsData);
}
return (
<>
<Header
data={data}
userIsAdminOrHasWritePerm={userIsAdminOrHasWritePerm}
isGraphView={isGraphView}
view={view}
{...headerHandlers}
{...params}
showCardHeader={!!cardsData?.length}
/>
{content}
<Modal
Expand All @@ -243,3 +284,8 @@ export default function Build({ user, userIsAdminOrHasWritePerm }) {
</>
);
}

Build.propTypes = {
user: PropTypes.shape().isRequired,
userIsAdminOrHasWritePerm: PropTypes.bool.isRequired,
};
Loading

0 comments on commit 774d83a

Please sign in to comment.