Initial Move from Azure DevOps to GitHub

This commit is contained in:
Steve Faulkner
2020-05-25 21:30:55 -05:00
commit 36581fb6d9
986 changed files with 195242 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
import { FontWeights } from "@uifabric/styling";
import { IIconStyles, ITextStyles } from "office-ui-fabric-react";
export const siteTextStyles: ITextStyles = {
root: {
color: "#025F52",
fontWeight: FontWeights.semibold
}
};
export const descriptionTextStyles: ITextStyles = {
root: {
color: "#333333",
fontWeight: FontWeights.semibold
}
};
export const subtleHelpfulTextStyles: ITextStyles = {
root: {
color: "#ccc",
fontWeight: FontWeights.regular
}
};
export const iconStyles: IIconStyles = {
root: {
marginLeft: "10px",
color: "#0078D4",
fontSize: 12,
fontWeight: FontWeights.regular,
display: "inline-block"
}
};
export const mainHelpfulTextStyles: ITextStyles = {
root: {
color: "#000",
fontWeight: FontWeights.regular
}
};
export const subtleIconStyles: IIconStyles = {
root: {
color: "#ddd",
fontSize: 12,
fontWeight: FontWeights.regular
}
};
export const helpfulTextStyles: ITextStyles = {
root: {
color: "#333333",
fontWeight: FontWeights.regular
}
};

View File

@@ -0,0 +1,65 @@
import * as React from "react";
import * as DataModels from "../../Contracts/DataModels";
import { Card, ICardTokens, ICardSectionTokens } from "@uifabric/react-cards";
import { Icon, Image, Persona, Text } from "office-ui-fabric-react";
import {
siteTextStyles,
descriptionTextStyles,
helpfulTextStyles,
subtleHelpfulTextStyles,
subtleIconStyles
} from "./CardStyleConstants";
interface GalleryCardComponentProps {
name: string;
url: string;
notebookMetadata: DataModels.NotebookMetadata;
onClick: () => void;
}
export class GalleryCardComponent extends React.Component<GalleryCardComponentProps> {
private cardTokens: ICardTokens = { childrenMargin: 12 };
private attendantsCardSectionTokens: ICardSectionTokens = { childrenGap: 6 };
public render(): JSX.Element {
return this.props.notebookMetadata != null ? (
<Card aria-label="Notebook Card" onClick={this.props.onClick} tokens={this.cardTokens}>
<Card.Item>
<Persona text={this.props.notebookMetadata.author} secondaryText={this.props.notebookMetadata.date} />
</Card.Item>
<Card.Item fill>
<Image src={this.props.notebookMetadata.imageUrl} width="100%" alt="Notebook display image" />
</Card.Item>
<Card.Section>
<Text variant="small" styles={siteTextStyles}>
{this.props.notebookMetadata.tags.join(", ")}
</Text>
<Text styles={descriptionTextStyles}>{this.props.name}</Text>
<Text variant="small" styles={helpfulTextStyles}>
{this.props.notebookMetadata.description}
</Text>
</Card.Section>
<Card.Section horizontal tokens={this.attendantsCardSectionTokens}>
<Icon iconName="RedEye" styles={subtleIconStyles} />
<Text variant="small" styles={subtleHelpfulTextStyles}>
{this.props.notebookMetadata.views}
</Text>
<Icon iconName="Download" styles={subtleIconStyles} />
<Text variant="small" styles={subtleHelpfulTextStyles}>
{this.props.notebookMetadata.downloads}
</Text>
<Icon iconName="Heart" styles={subtleIconStyles} />
<Text variant="small" styles={subtleHelpfulTextStyles}>
{this.props.notebookMetadata.likes}
</Text>
</Card.Section>
</Card>
) : (
<Card aria-label="Notebook Card" onClick={this.props.onClick} tokens={this.cardTokens}>
<Card.Section>
<Text styles={descriptionTextStyles}>{this.props.name}</Text>
</Card.Section>
</Card>
);
}
}

View File

@@ -0,0 +1,9 @@
@import "../../less/Common/Constants";
.galleryContainer {
padding: @DefaultSpace;
height: 100%;
overflow-y: scroll;
width: 100%;
font-family: @DataExplorerFont;
}

View File

@@ -0,0 +1,20 @@
import * as ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.css";
import "./GalleryViewer.less";
import { GalleryViewerComponent } from "./GalleryViewerComponent";
import { JunoUtils } from "../Utils/JunoUtils";
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
const onInit = async () => {
initializeIcons();
const officialSamplesData = await JunoUtils.getOfficialSampleNotebooks();
const galleryViewerComponent = new GalleryViewerComponent({
officialSamplesData: officialSamplesData,
likedNotebookData: undefined,
container: undefined
});
ReactDOM.render(galleryViewerComponent.render(), document.getElementById("galleryContent"));
};
// Entry point
window.addEventListener("load", onInit);

View File

@@ -0,0 +1,207 @@
/**
* Gallery Viewer
*/
import * as React from "react";
import * as DataModels from "../Contracts/DataModels";
import * as ViewModels from "../Contracts/ViewModels";
import { GalleryCardComponent } from "./Cards/GalleryCardComponent";
import { Stack, IStackTokens } from "office-ui-fabric-react";
import AppBar from "@material-ui/core/AppBar";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import Typography from "@material-ui/core/Typography";
import Box from "@material-ui/core/Box";
import { JunoUtils } from "../Utils/JunoUtils";
import { CosmosClient } from "../Common/CosmosClient";
import { config } from "../Config";
import path from "path";
import { SessionStorageUtility, StorageKey } from "../Shared/StorageUtility";
import "./GalleryViewer.less";
interface GalleryCardsComponentProps {
data: DataModels.GitHubInfoJunoResponse[];
onClick: (url: string, notebookMetadata: DataModels.NotebookMetadata) => Promise<void>;
}
class GalleryCardsComponent extends React.Component<GalleryCardsComponentProps> {
private sectionStackTokens: IStackTokens = { childrenGap: 30 };
public render(): JSX.Element {
return (
<Stack horizontal wrap tokens={this.sectionStackTokens}>
{this.props.data.map((githubInfo: DataModels.GitHubInfoJunoResponse, index: any) => {
const name = githubInfo.name;
const url = githubInfo.downloadUrl;
const notebookMetadata = githubInfo.metadata;
return (
name !== ".gitignore" &&
url && (
<GalleryCardComponent
key={url}
name={name}
url={url}
notebookMetadata={notebookMetadata}
onClick={() => this.props.onClick(url, notebookMetadata)}
/>
)
);
})}
</Stack>
);
}
}
const TabPanel = (props: any) => (
<Typography
component="div"
role="tabpanel"
hidden={props.value !== props.index}
id={`full-width-tabpanel-${props.index}`}
aria-labelledby={`full-width-tab-${props.index}`}
>
{props.value === props.index && <Box p={2}>{props.children}</Box>}
</Typography>
);
const a11yProps = (index: number) => {
return {
id: `full-width-tab-${index}`,
"aria-controls": `full-width-tabpanel-${index}`
};
};
interface FullWidthTabsProps {
officialSamplesContent: DataModels.GitHubInfoJunoResponse[];
likedNotebooksContent: DataModels.GitHubInfoJunoResponse[];
onClick: (url: string, notebookMetadata: DataModels.NotebookMetadata) => Promise<void>;
}
const FullWidthTabs = (props: FullWidthTabsProps) => {
const [value, setValue] = React.useState(0);
const handleChange = ({}, newValue: any) => {
setValue(newValue);
};
return (
<>
<AppBar position="static" color="transparent" style={{ background: "transparent", boxShadow: "none" }}>
<Tabs
value={value}
onChange={handleChange}
indicatorColor="primary"
textColor="primary"
aria-label="gallery tabs"
>
<Tab label="Official Samples" {...a11yProps(0)} />
<Tab label="Liked Notebooks" {...a11yProps(1)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<GalleryCardsComponent data={props.officialSamplesContent} onClick={props.onClick} />
</TabPanel>
<TabPanel value={value} index={1}>
<GalleryCardsComponent data={props.likedNotebooksContent} onClick={props.onClick} />
</TabPanel>
</>
);
};
export interface GalleryViewerContainerComponentProps {
container: ViewModels.Explorer;
}
export interface GalleryViewerContainerComponentState {
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
likedNotebooksData: DataModels.LikedNotebooksJunoResponse;
}
export class GalleryViewerContainerComponent extends React.Component<
GalleryViewerContainerComponentProps,
GalleryViewerContainerComponentState
> {
constructor(props: GalleryViewerContainerComponentProps) {
super(props);
this.state = {
officialSamplesData: undefined,
likedNotebooksData: undefined
};
}
componentDidMount() {
JunoUtils.getOfficialSampleNotebooks().then((data1: DataModels.GitHubInfoJunoResponse[]) => {
const officialSamplesData = data1;
JunoUtils.getLikedNotebooks(CosmosClient.authorizationToken()).then(
(data2: DataModels.LikedNotebooksJunoResponse) => {
const likedNotebooksData = data2;
this.setState({
officialSamplesData: officialSamplesData,
likedNotebooksData: likedNotebooksData
});
}
);
});
}
public render(): JSX.Element {
return this.state.officialSamplesData && this.state.likedNotebooksData ? (
<GalleryViewerComponent
container={this.props.container}
officialSamplesData={this.state.officialSamplesData}
likedNotebookData={this.state.likedNotebooksData}
/>
) : (
<></>
);
}
}
export interface GalleryViewerComponentProps {
container: ViewModels.Explorer;
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
likedNotebookData: DataModels.LikedNotebooksJunoResponse;
}
export class GalleryViewerComponent extends React.Component<GalleryViewerComponentProps> {
private authorizationToken = CosmosClient.authorizationToken();
public render(): JSX.Element {
return this.props.container ? (
<div className="galleryContainer">
<FullWidthTabs
officialSamplesContent={this.props.officialSamplesData}
likedNotebooksContent={this.props.likedNotebookData.likedNotebooksContent}
onClick={this.openNotebookViewer}
/>
</div>
) : (
<div className="galleryContainer">
<GalleryCardsComponent data={this.props.officialSamplesData} onClick={this.openNotebookViewer} />
</div>
);
}
public getOfficialSamplesData(): DataModels.GitHubInfoJunoResponse[] {
return this.props.officialSamplesData;
}
public getLikedNotebookData(): DataModels.LikedNotebooksJunoResponse {
return this.props.likedNotebookData;
}
public openNotebookViewer = async (url: string, notebookMetadata: DataModels.NotebookMetadata) => {
if (!this.props.container) {
SessionStorageUtility.setEntryString(
StorageKey.NotebookMetadata,
notebookMetadata ? JSON.stringify(notebookMetadata) : null
);
SessionStorageUtility.setEntryString(StorageKey.NotebookName, path.basename(url));
window.open(`${config.hostedExplorerURL}notebookViewer.html?notebookurl=${url}`, "_blank");
} else {
this.props.container.openNotebookViewer(url, notebookMetadata);
}
};
}

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
<title>Gallery Viewer</title>
</head>
<body>
<div class="galleryComponentContainer" id="galleryContent"></div>
</body>
</html>